If custom formats are provided, run validation logic against them. This also was an opportunity to make the ServiceConfiguration validation logic reusable between Sonarr and Radarr.pull/139/head
parent
1ca192f3e5
commit
cda317d3c3
@ -0,0 +1,62 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using FluentValidation;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Recyclarr.TestLibrary;
|
||||||
|
using TrashLib.Config.Services;
|
||||||
|
|
||||||
|
namespace TrashLib.Tests.Config.Services;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[Parallelizable(ParallelScope.All)]
|
||||||
|
public class ServiceConfigurationTest : IntegrationFixture
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Validation_fails_for_all_missing_required_properties()
|
||||||
|
{
|
||||||
|
// default construct which should yield default values (invalid) for all required properties
|
||||||
|
var config = new ServiceConfiguration();
|
||||||
|
|
||||||
|
var validator = ServiceLocator.Resolve<IValidator<ServiceConfiguration>>();
|
||||||
|
|
||||||
|
var result = validator.Validate(config);
|
||||||
|
|
||||||
|
var messages = new ServiceValidationMessages();
|
||||||
|
var expectedErrorMessageSubstrings = new[]
|
||||||
|
{
|
||||||
|
messages.ApiKey,
|
||||||
|
messages.BaseUrl
|
||||||
|
};
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
result.Errors.Select(e => e.ErrorMessage)
|
||||||
|
.Should().BeEquivalentTo(expectedErrorMessageSubstrings);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Fail_when_trash_ids_missing()
|
||||||
|
{
|
||||||
|
var config = new ServiceConfiguration
|
||||||
|
{
|
||||||
|
BaseUrl = "valid",
|
||||||
|
ApiKey = "valid",
|
||||||
|
CustomFormats = new List<CustomFormatConfig>
|
||||||
|
{
|
||||||
|
new() // Empty to force validation failure
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var validator = ServiceLocator.Resolve<IValidator<ServiceConfiguration>>();
|
||||||
|
|
||||||
|
var result = validator.Validate(config);
|
||||||
|
|
||||||
|
var messages = new ServiceValidationMessages();
|
||||||
|
var expectedErrorMessageSubstrings = new[]
|
||||||
|
{
|
||||||
|
messages.CustomFormatTrashIds
|
||||||
|
};
|
||||||
|
|
||||||
|
result.IsValid.Should().BeFalse();
|
||||||
|
result.Errors.Select(e => e.ErrorMessage)
|
||||||
|
.Should().BeEquivalentTo(expectedErrorMessageSubstrings);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace TrashLib.Config.Services;
|
||||||
|
|
||||||
|
public interface IServiceValidationMessages
|
||||||
|
{
|
||||||
|
string BaseUrl { get; }
|
||||||
|
string ApiKey { get; }
|
||||||
|
string CustomFormatTrashIds { get; }
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using TrashLib.Services.Radarr.Config;
|
||||||
|
|
||||||
|
namespace TrashLib.Config.Services;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
internal class ServiceConfigurationValidator : AbstractValidator<ServiceConfiguration>
|
||||||
|
{
|
||||||
|
public ServiceConfigurationValidator(
|
||||||
|
IServiceValidationMessages messages,
|
||||||
|
IValidator<CustomFormatConfig> customFormatConfigValidator)
|
||||||
|
{
|
||||||
|
RuleFor(x => x.BaseUrl).NotEmpty().WithMessage(messages.BaseUrl);
|
||||||
|
RuleFor(x => x.ApiKey).NotEmpty().WithMessage(messages.ApiKey);
|
||||||
|
RuleForEach(x => x.CustomFormats).SetValidator(customFormatConfigValidator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
internal class CustomFormatConfigValidator : AbstractValidator<CustomFormatConfig>
|
||||||
|
{
|
||||||
|
public CustomFormatConfigValidator(
|
||||||
|
IServiceValidationMessages messages,
|
||||||
|
IValidator<QualityProfileScoreConfig> qualityProfileScoreConfigValidator)
|
||||||
|
{
|
||||||
|
RuleFor(x => x.TrashIds).NotEmpty().WithMessage(messages.CustomFormatTrashIds);
|
||||||
|
RuleForEach(x => x.QualityProfiles).SetValidator(qualityProfileScoreConfigValidator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
internal class QualityProfileScoreConfigValidator : AbstractValidator<QualityProfileScoreConfig>
|
||||||
|
{
|
||||||
|
public QualityProfileScoreConfigValidator(IRadarrValidationMessages messages)
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Name).NotEmpty().WithMessage(messages.QualityProfileName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
namespace TrashLib.Config.Services;
|
||||||
|
|
||||||
|
internal /*abstract*/ class ServiceValidationMessages : IServiceValidationMessages
|
||||||
|
{
|
||||||
|
public string BaseUrl =>
|
||||||
|
"Property 'base_url' is required";
|
||||||
|
|
||||||
|
public string ApiKey =>
|
||||||
|
"Property 'api_key' is required";
|
||||||
|
|
||||||
|
public string CustomFormatTrashIds =>
|
||||||
|
"'custom_formats' elements must contain at least one element under 'trash_ids'";
|
||||||
|
}
|
Loading…
Reference in new issue