mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
61 changed files with 888 additions and 470 deletions
@ -0,0 +1,59 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
using Squidex.Infrastructure.Translations; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.ValidateContent.Validators |
|||
{ |
|||
public sealed class UniqueObjectValuesValidator : IValidator |
|||
{ |
|||
private readonly IEnumerable<string> fields; |
|||
|
|||
public UniqueObjectValuesValidator(IEnumerable<string> fields) |
|||
{ |
|||
this.fields = fields; |
|||
} |
|||
|
|||
public Task ValidateAsync(object? value, ValidationContext context, AddError addError) |
|||
{ |
|||
if (value is IEnumerable<JsonObject> objects && objects.Count() > 1) |
|||
{ |
|||
Validate(context, addError, objects); |
|||
} |
|||
else if (value is IEnumerable<Component> components && components.Count() > 1) |
|||
{ |
|||
Validate(context, addError, components.Select(x => x.Data)); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
private void Validate(ValidationContext context, AddError addError, IEnumerable<JsonObject> items) |
|||
{ |
|||
var duplicates = new HashSet<IJsonValue>(10); |
|||
|
|||
foreach (var field in fields) |
|||
{ |
|||
duplicates.Clear(); |
|||
|
|||
foreach (var item in items) |
|||
{ |
|||
if (item.TryGetValue(field, out var fieldValue) && !duplicates.Add(fieldValue)) |
|||
{ |
|||
addError(context.Path, T.Get("contents.validation.uniqueObjectValues", new { field })); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,118 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using FluentAssertions; |
|||
using Squidex.Domain.Apps.Core.TestHelpers; |
|||
using Squidex.Domain.Apps.Core.ValidateContent.Validators; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Operations.ValidateContent.Validators |
|||
{ |
|||
public class UniqueObjectValuesValidatorTests : IClassFixture<TranslationsFixture> |
|||
{ |
|||
private readonly List<string> errors = new List<string>(); |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_errors_if_value_is_invalid() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString" }); |
|||
|
|||
await sut.ValidateAsync(1, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_errors_if_value_is_null() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString" }); |
|||
|
|||
await sut.ValidateAsync(null, errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_objects_contain_not_duplicates() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString" }); |
|||
|
|||
await sut.ValidateAsync(new[] |
|||
{ |
|||
new JsonObject() |
|||
.Add("myString", "1"), |
|||
new JsonObject() |
|||
.Add("myString", "2") |
|||
}, |
|||
errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_not_add_error_if_objects_contain_unchecked_duplicates() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString" }); |
|||
|
|||
await sut.ValidateAsync(new[] |
|||
{ |
|||
new JsonObject() |
|||
.Add("other", "1"), |
|||
new JsonObject() |
|||
.Add("other", "1") |
|||
}, |
|||
errors); |
|||
|
|||
Assert.Empty(errors); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_error_if_objects_contain_duplicates() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString" }); |
|||
|
|||
await sut.ValidateAsync(new[] |
|||
{ |
|||
new JsonObject() |
|||
.Add("myString", "1"), |
|||
new JsonObject() |
|||
.Add("myString", "1") |
|||
}, |
|||
errors); |
|||
|
|||
errors.Should().BeEquivalentTo( |
|||
new[] { "Must not contain items with duplicate 'myString' fields." }); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_add_errors_if_objects_contain_multiple_duplicates() |
|||
{ |
|||
var sut = new UniqueObjectValuesValidator(new[] { "myString", "myNumber" }); |
|||
|
|||
await sut.ValidateAsync(new[] |
|||
{ |
|||
new JsonObject() |
|||
.Add("myString", "1") |
|||
.Add("myNumber", 1), |
|||
new JsonObject() |
|||
.Add("myString", "1") |
|||
.Add("myNumber", 1), |
|||
}, |
|||
errors); |
|||
|
|||
errors.Should().BeEquivalentTo( |
|||
new[] |
|||
{ |
|||
"Must not contain items with duplicate 'myString' fields.", |
|||
"Must not contain items with duplicate 'myNumber' fields." |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue