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