mirror of https://github.com/Squidex/squidex.git
17 changed files with 281 additions and 156 deletions
@ -1,25 +0,0 @@ |
|||
// ==========================================================================
|
|||
// AssetsValue.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas |
|||
{ |
|||
public sealed class AssetsValue |
|||
{ |
|||
private static readonly List<Guid> EmptyAssetIds = new List<Guid>(); |
|||
|
|||
public IReadOnlyList<Guid> AssetIds { get; } |
|||
|
|||
public AssetsValue(IReadOnlyList<Guid> assetIds) |
|||
{ |
|||
AssetIds = assetIds ?? EmptyAssetIds; |
|||
} |
|||
} |
|||
} |
|||
@ -1,25 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ReferencesValue.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas |
|||
{ |
|||
public sealed class ReferencesValue |
|||
{ |
|||
private static readonly List<Guid> EmptyReferencedIds = new List<Guid>(); |
|||
|
|||
public IReadOnlyList<Guid> ContentIds { get; } |
|||
|
|||
public ReferencesValue(IReadOnlyList<Guid> assetIds) |
|||
{ |
|||
ContentIds = assetIds ?? EmptyReferencedIds; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// ==========================================================================
|
|||
// CollectionItemValidator.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas.Validators |
|||
{ |
|||
public sealed class CollectionItemValidator<T> : IValidator |
|||
{ |
|||
private readonly IValidator[] itemValidators; |
|||
|
|||
public CollectionItemValidator(params IValidator[] itemValidators) |
|||
{ |
|||
Guard.NotNull(itemValidators, nameof(itemValidators)); |
|||
Guard.NotEmpty(itemValidators, nameof(itemValidators)); |
|||
|
|||
this.itemValidators = itemValidators; |
|||
} |
|||
|
|||
public async Task ValidateAsync(object value, ValidationContext context, Action<string> addError) |
|||
{ |
|||
if (value is ICollection<T> items) |
|||
{ |
|||
var index = 1; |
|||
|
|||
foreach (var item in items) |
|||
{ |
|||
foreach (var itemValidator in itemValidators) |
|||
{ |
|||
await itemValidator.ValidateAsync(item, context, e => addError(e.Replace("<FIELD>", $"<FIELD> item #{index}"))); |
|||
} |
|||
|
|||
index++; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// CollectionValidator.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.Domain.Apps.Core.Schemas.Validators |
|||
{ |
|||
public sealed class CollectionValidator<T> : IValidator |
|||
{ |
|||
private readonly bool isRequired; |
|||
private readonly int? minItems; |
|||
private readonly int? maxItems; |
|||
|
|||
public CollectionValidator(bool isRequired, int? minItems = null, int? maxItems = null) |
|||
{ |
|||
this.isRequired = isRequired; |
|||
this.minItems = minItems; |
|||
this.maxItems = maxItems; |
|||
} |
|||
|
|||
public Task ValidateAsync(object value, ValidationContext context, Action<string> addError) |
|||
{ |
|||
if (!(value is ICollection<T> items) || items.Count == 0) |
|||
{ |
|||
if (isRequired && !context.IsOptional) |
|||
{ |
|||
addError("<FIELD> is required."); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
if (minItems.HasValue && items.Count < minItems.Value) |
|||
{ |
|||
addError($"<FIELD> must have at least {minItems} item(s)."); |
|||
} |
|||
|
|||
if (maxItems.HasValue && items.Count > maxItems.Value) |
|||
{ |
|||
addError($"<FIELD> must have not more than {maxItems} item(s)."); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
// ==========================================================================
|
|||
// CollectionValidatorTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FluentAssertions; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas.Validators |
|||
{ |
|||
public class CollectionItemValidatorTests |
|||
{ |
|||
private readonly List<string> errors = new List<string>(); |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_value_is_wrong_type() |
|||
{ |
|||
var sut = new CollectionItemValidator<int>(new RangeValidator<int>(2, 4)); |
|||
|
|||
await sut.ValidateAsync(true, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_all_values_are_valid() |
|||
{ |
|||
var sut = new CollectionItemValidator<int>(new RangeValidator<int>(2, 4)); |
|||
|
|||
await sut.ValidateAsync(new List<int> { 2, 3, 4 }, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_at_least_one_item_is_not_valid() |
|||
{ |
|||
var sut = new CollectionItemValidator<int>(new RangeValidator<int>(2, 4)); |
|||
|
|||
await sut.ValidateAsync(new List<int> { 2, 1, 4, 5 }, errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] |
|||
{ |
|||
"<FIELD> item #2 must be greater or equals than '2'.", |
|||
"<FIELD> item #4 must be less or equals than '4'." |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// ==========================================================================
|
|||
// CollectionValidatorTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FluentAssertions; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Schemas.Validators |
|||
{ |
|||
public class CollectionValidatorTests |
|||
{ |
|||
private readonly List<string> errors = new List<string>(); |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_value_is_valid() |
|||
{ |
|||
var sut = new CollectionValidator<int>(true, 1, 3); |
|||
|
|||
await sut.ValidateAsync(new List<int> { 1, 2 }, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_optional() |
|||
{ |
|||
var sut = new CollectionValidator<int>(true, 1, 3); |
|||
|
|||
await sut.ValidateOptionalAsync(null, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_value_is_null() |
|||
{ |
|||
var sut = new CollectionValidator<int>(true, 1, 3); |
|||
|
|||
await sut.ValidateAsync(null, errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "<FIELD> is required." }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_collection_has_too_few_items() |
|||
{ |
|||
var sut = new CollectionValidator<int>(true, 2, 3); |
|||
|
|||
await sut.ValidateAsync(new List<int> { 1 }, errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "<FIELD> must have at least 2 item(s)." }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_collection_has_too_many_items() |
|||
{ |
|||
var sut = new CollectionValidator<int>(true, 2, 3); |
|||
|
|||
await sut.ValidateAsync(new List<int> { 1, 2, 3, 4 }, errors); |
|||
|
|||
errors.ShouldBeEquivalentTo( |
|||
new[] { "<FIELD> must have not more than 3 item(s)." }); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue