diff --git a/src/NzbDrone.Api.Test/v3/Qualities/QualityDefinitionResourceValidatorTest.cs b/src/NzbDrone.Api.Test/v3/Qualities/QualityDefinitionResourceValidatorTest.cs new file mode 100644 index 000000000..f01d7f512 --- /dev/null +++ b/src/NzbDrone.Api.Test/v3/Qualities/QualityDefinitionResourceValidatorTest.cs @@ -0,0 +1,99 @@ +using FluentValidation.TestHelper; +using NUnit.Framework; +using NzbDrone.Core.Qualities; +using Sonarr.Api.V3.Qualities; + +namespace NzbDrone.Api.Test.v3.Qualities; + +[Parallelizable(ParallelScope.All)] +public class QualityDefinitionResourceValidatorTests +{ + private readonly QualityDefinitionResourceValidator _validator; + private readonly QualityDefinitionLimits _limits; + + public QualityDefinitionResourceValidatorTests() + { + _limits = new QualityDefinitionLimits(); + _validator = new QualityDefinitionResourceValidator(_limits); + } + + [Test] + public void Validate_fails_when_min_size_is_below_min_limit() + { + var resource = new QualityDefinitionResource { MinSize = _limits.MinLimit - 1 }; + + var result = _validator.TestValidate(resource); + + result.ShouldHaveValidationErrorFor(r => r.MinSize) + .WithErrorCode("GreaterThanOrEqualTo"); + } + + [Test] + public void Validate_fails_when_min_size_is_above_preferred_size() + { + var resource = new QualityDefinitionResource + { + MinSize = 10, + PreferredSize = 5 + }; + + var result = _validator.TestValidate(resource); + + result.ShouldHaveValidationErrorFor(r => r.MinSize) + .WithErrorCode("LessThanOrEqualTo"); + } + + [Test] + public void Validate_passes_when_min_size_is_within_limits() + { + var resource = new QualityDefinitionResource + { + MinSize = _limits.MinLimit, + PreferredSize = _limits.MaxLimit + }; + + var result = _validator.TestValidate(resource); + + result.ShouldNotHaveAnyValidationErrors(); + } + + [Test] + public void Validate_fails_when_max_size_is_below_preferred_size() + { + var resource = new QualityDefinitionResource + { + MaxSize = 5, + PreferredSize = 10 + }; + + var result = _validator.TestValidate(resource); + + result.ShouldHaveValidationErrorFor(r => r.MaxSize) + .WithErrorCode("GreaterThanOrEqualTo"); + } + + [Test] + public void Validate_fails_when_max_size_exceeds_max_limit() + { + var resource = new QualityDefinitionResource { MaxSize = _limits.MaxLimit + 1 }; + + var result = _validator.TestValidate(resource); + + result.ShouldHaveValidationErrorFor(r => r.MaxSize) + .WithErrorCode("LessThanOrEqualTo"); + } + + [Test] + public void Validate_passes_when_max_size_is_within_limits() + { + var resource = new QualityDefinitionResource + { + MaxSize = _limits.MaxLimit, + PreferredSize = _limits.MinLimit + }; + + var result = _validator.TestValidate(resource); + + result.ShouldNotHaveAnyValidationErrors(); + } +} diff --git a/src/Sonarr.Api.V3/Qualities/QualityDefinitionController.cs b/src/Sonarr.Api.V3/Qualities/QualityDefinitionController.cs index 19aab3d68..03c9c31f4 100644 --- a/src/Sonarr.Api.V3/Qualities/QualityDefinitionController.cs +++ b/src/Sonarr.Api.V3/Qualities/QualityDefinitionController.cs @@ -20,6 +20,15 @@ public QualityDefinitionController(IQualityDefinitionService qualityDefinitionSe : base(signalRBroadcaster) { _qualityDefinitionService = qualityDefinitionService; + + SetupValidation(qualityDefinitionService); + } + + private void SetupValidation(IQualityDefinitionService qualityDefinitionService) + { + var limits = qualityDefinitionService.GetLimits(); + SharedValidator.RuleFor(c => c) + .SetValidator(new QualityDefinitionResourceValidator(limits)); } [RestPutById] diff --git a/src/Sonarr.Api.V3/Qualities/QualityDefinitionResourceValidator.cs b/src/Sonarr.Api.V3/Qualities/QualityDefinitionResourceValidator.cs new file mode 100644 index 000000000..8a178e6d2 --- /dev/null +++ b/src/Sonarr.Api.V3/Qualities/QualityDefinitionResourceValidator.cs @@ -0,0 +1,28 @@ +using FluentValidation; +using NzbDrone.Core.Qualities; + +namespace Sonarr.Api.V3.Qualities; + +public class QualityDefinitionResourceValidator : AbstractValidator +{ + public QualityDefinitionResourceValidator(QualityDefinitionLimits limits) + { + When(c => c.MinSize is not null, () => + { + RuleFor(c => c.MinSize) + .GreaterThanOrEqualTo(limits.MinLimit) + .WithErrorCode("GreaterThanOrEqualTo") + .LessThanOrEqualTo(c => c.PreferredSize ?? limits.MaxLimit) + .WithErrorCode("LessThanOrEqualTo"); + }); + + When(c => c.MaxSize is not null, () => + { + RuleFor(c => c.MaxSize) + .GreaterThanOrEqualTo(c => c.PreferredSize ?? limits.MinLimit) + .WithErrorCode("GreaterThanOrEqualTo") + .LessThanOrEqualTo(limits.MaxLimit) + .WithErrorCode("LessThanOrEqualTo"); + }); + } +}