diff --git a/src/Recyclarr.Cli/Cache/CacheStoragePath.cs b/src/Recyclarr.Cli/Cache/CacheStoragePath.cs index 218f9d5f..7fc24173 100644 --- a/src/Recyclarr.Cli/Cache/CacheStoragePath.cs +++ b/src/Recyclarr.Cli/Cache/CacheStoragePath.cs @@ -7,17 +7,17 @@ using Recyclarr.Platform; namespace Recyclarr.Cli.Cache; -public class CacheStoragePath(IAppPaths paths) : ICacheStoragePath +public class CacheStoragePath(IAppPaths paths, IServiceConfiguration config) : ICacheStoragePath { private readonly IFNV1a _hash = FNV1aFactory.Instance.Create(FNVConfig.GetPredefinedConfig(64)); - private string BuildUniqueServiceDir(IServiceConfiguration config) + private string BuildUniqueServiceDir() { var url = config.BaseUrl.OriginalString; return _hash.ComputeHash(Encoding.ASCII.GetBytes(url)).AsHexString(); } - private IFileInfo CalculatePathInternal(IServiceConfiguration config, string cacheObjectName, string serviceDir) + private IFileInfo CalculatePathInternal(string cacheObjectName, string serviceDir) { return paths.CacheDirectory .SubDirectory(config.ServiceType.ToString().ToLower(CultureInfo.CurrentCulture)) @@ -25,8 +25,8 @@ public class CacheStoragePath(IAppPaths paths) : ICacheStoragePath .File(cacheObjectName + ".json"); } - public IFileInfo CalculatePath(IServiceConfiguration config, string cacheObjectName) + public IFileInfo CalculatePath(string cacheObjectName) { - return CalculatePathInternal(config, cacheObjectName, BuildUniqueServiceDir(config)); + return CalculatePathInternal(cacheObjectName, BuildUniqueServiceDir()); } } diff --git a/src/Recyclarr.Cli/Cache/ICacheStoragePath.cs b/src/Recyclarr.Cli/Cache/ICacheStoragePath.cs index f783028d..f2a8f3c2 100644 --- a/src/Recyclarr.Cli/Cache/ICacheStoragePath.cs +++ b/src/Recyclarr.Cli/Cache/ICacheStoragePath.cs @@ -1,9 +1,8 @@ using System.IO.Abstractions; -using Recyclarr.Config.Models; namespace Recyclarr.Cli.Cache; public interface ICacheStoragePath { - IFileInfo CalculatePath(IServiceConfiguration config, string cacheObjectName); + IFileInfo CalculatePath(string cacheObjectName); } diff --git a/src/Recyclarr.Cli/Cache/IServiceCache.cs b/src/Recyclarr.Cli/Cache/IServiceCache.cs index 48db7295..a77141ee 100644 --- a/src/Recyclarr.Cli/Cache/IServiceCache.cs +++ b/src/Recyclarr.Cli/Cache/IServiceCache.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Cli.Cache; public interface IServiceCache { - T? Load(IServiceConfiguration config) where T : class; - void Save(T obj, IServiceConfiguration config) where T : class; + T? Load() where T : class; + void Save(T obj) where T : class; } diff --git a/src/Recyclarr.Cli/Cache/ServiceCache.cs b/src/Recyclarr.Cli/Cache/ServiceCache.cs index 9cf387fe..33d6ebc0 100644 --- a/src/Recyclarr.Cli/Cache/ServiceCache.cs +++ b/src/Recyclarr.Cli/Cache/ServiceCache.cs @@ -3,7 +3,6 @@ using System.Reflection; using System.Text.Json; using System.Text.RegularExpressions; using Recyclarr.Common.Extensions; -using Recyclarr.Config.Models; using Recyclarr.Json; namespace Recyclarr.Cli.Cache; @@ -12,9 +11,9 @@ public partial class ServiceCache(ICacheStoragePath storagePath, ILogger log) : { private readonly JsonSerializerOptions _jsonSettings = GlobalJsonSerializerSettings.Recyclarr; - public T? Load(IServiceConfiguration config) where T : class + public T? Load() where T : class { - var path = PathFromAttribute(config); + var path = PathFromAttribute(); log.Debug("Loading cache from path: {Path}", path.FullName); if (!path.Exists) { @@ -35,9 +34,9 @@ public partial class ServiceCache(ICacheStoragePath storagePath, ILogger log) : return null; } - public void Save(T obj, IServiceConfiguration config) where T : class + public void Save(T obj) where T : class { - var path = PathFromAttribute(config); + var path = PathFromAttribute(); log.Debug("Saving cache to path: {Path}", path.FullName); path.CreateParentDirectory(); @@ -56,7 +55,7 @@ public partial class ServiceCache(ICacheStoragePath storagePath, ILogger log) : return attribute.Name; } - private IFileInfo PathFromAttribute(IServiceConfiguration config) + private IFileInfo PathFromAttribute() { var objectName = GetCacheObjectNameAttribute(); if (!AllowedObjectNameCharactersRegex().IsMatch(objectName)) @@ -64,7 +63,7 @@ public partial class ServiceCache(ICacheStoragePath storagePath, ILogger log) : throw new ArgumentException($"Object name '{objectName}' has unacceptable characters"); } - return storagePath.CalculatePath(config, objectName); + return storagePath.CalculatePath(objectName); } [GeneratedRegex(@"^[\w-]+$", RegexOptions.None, 1000)] diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/CustomFormatCachePersister.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/CustomFormatCachePersister.cs index 9c17adc4..1c754487 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/CustomFormatCachePersister.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/CustomFormatCachePersister.cs @@ -4,13 +4,16 @@ using Recyclarr.Config.Models; namespace Recyclarr.Cli.Pipelines.CustomFormat.Cache; -public class CustomFormatCachePersister(ILogger log, IServiceCache serviceCache) : ICustomFormatCachePersister +public class CustomFormatCachePersister( + ILogger log, + IServiceCache serviceCache, + IServiceConfiguration config) : ICustomFormatCachePersister { public const int LatestVersion = 1; - public CustomFormatCache Load(IServiceConfiguration config) + public CustomFormatCache Load() { - var cacheData = serviceCache.Load(config); + var cacheData = serviceCache.Load(); if (cacheData == null) { log.Debug("Custom format cache does not exist; proceeding without it"); @@ -29,10 +32,10 @@ public class CustomFormatCachePersister(ILogger log, IServiceCache serviceCache) return new CustomFormatCache(cacheData.TrashIdMappings); } - public void Save(IServiceConfiguration config, CustomFormatCache cache) + public void Save(CustomFormatCache cache) { var data = new CustomFormatCacheData(LatestVersion, config.InstanceName, cache.Mappings); log.Debug("Saving Custom Format Cache with {Mappings}", JsonSerializer.Serialize(data.TrashIdMappings)); - serviceCache.Save(data, config); + serviceCache.Save(data); } } diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/ICustomFormatCachePersister.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/ICustomFormatCachePersister.cs index 64080208..559d749d 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/ICustomFormatCachePersister.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/Cache/ICustomFormatCachePersister.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Cli.Pipelines.CustomFormat.Cache; public interface ICustomFormatCachePersister { - CustomFormatCache Load(IServiceConfiguration config); - void Save(IServiceConfiguration config, CustomFormatCache cache); + CustomFormatCache Load(); + void Save(CustomFormatCache cache); } diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiFetchPhase.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiFetchPhase.cs index c6c6c8d2..436ed68a 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiFetchPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiFetchPhase.cs @@ -1,6 +1,5 @@ using Recyclarr.Cli.Pipelines.Generic; using Recyclarr.Common.Extensions; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.CustomFormat; namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; @@ -8,9 +7,9 @@ namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; public class CustomFormatApiFetchPhase(ICustomFormatApiService api) : IApiFetchPipelinePhase { - public async Task Execute(CustomFormatPipelineContext context, IServiceConfiguration config) + public async Task Execute(CustomFormatPipelineContext context) { - var result = await api.GetCustomFormats(config); + var result = await api.GetCustomFormats(); context.ApiFetchOutput.AddRange(result); context.Cache.RemoveStale(result); } diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiPersistencePhase.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiPersistencePhase.cs index 7b6ca3ab..2b4c74e3 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiPersistencePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatApiPersistencePhase.cs @@ -1,6 +1,5 @@ using Recyclarr.Cli.Pipelines.CustomFormat.Cache; using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.CustomFormat; namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; @@ -8,13 +7,13 @@ namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; public class CustomFormatApiPersistencePhase(ICustomFormatApiService api, ICustomFormatCachePersister cachePersister) : IApiPersistencePipelinePhase { - public async Task Execute(CustomFormatPipelineContext context, IServiceConfiguration config) + public async Task Execute(CustomFormatPipelineContext context) { var transactions = context.TransactionOutput; foreach (var cf in transactions.NewCustomFormats) { - var response = await api.CreateCustomFormat(config, cf); + var response = await api.CreateCustomFormat(cf); if (response is not null) { cf.Id = response.Id; @@ -23,15 +22,15 @@ public class CustomFormatApiPersistencePhase(ICustomFormatApiService api, ICusto foreach (var dto in transactions.UpdatedCustomFormats) { - await api.UpdateCustomFormat(config, dto); + await api.UpdateCustomFormat(dto); } foreach (var map in transactions.DeletedCustomFormats) { - await api.DeleteCustomFormat(config, map.CustomFormatId); + await api.DeleteCustomFormat(map.CustomFormatId); } context.Cache.Update(transactions); - cachePersister.Save(config, context.Cache); + cachePersister.Save(context.Cache); } } diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs index 77a7f4df..b4f1b3f6 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhase.cs @@ -10,10 +10,11 @@ namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; public class CustomFormatConfigPhase( ICustomFormatGuideService guide, ProcessedCustomFormatCache cache, - ICustomFormatCachePersister cachePersister) + ICustomFormatCachePersister cachePersister, + IServiceConfiguration config) : IConfigPipelinePhase { - public Task Execute(CustomFormatPipelineContext context, IServiceConfiguration config) + public Task Execute(CustomFormatPipelineContext context) { // Match custom formats in the YAML config to those in the guide, by Trash ID // @@ -33,7 +34,7 @@ public class CustomFormatConfigPhase( context.InvalidFormats = processedCfs[false].Select(x => x.Id).ToList(); context.ConfigOutput.AddRange(processedCfs[true].SelectMany(x => x.CustomFormats)); - context.Cache = cachePersister.Load(config); + context.Cache = cachePersister.Load(); cache.AddCustomFormats(context.ConfigOutput); return Task.CompletedTask; diff --git a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatTransactionPhase.cs b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatTransactionPhase.cs index 8dc2416f..81558c21 100644 --- a/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatTransactionPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/CustomFormat/PipelinePhases/CustomFormatTransactionPhase.cs @@ -6,9 +6,10 @@ using Recyclarr.TrashGuide.CustomFormat; namespace Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; -public class CustomFormatTransactionPhase(ILogger log) : ITransactionPipelinePhase +public class CustomFormatTransactionPhase(ILogger log, IServiceConfiguration config) + : ITransactionPipelinePhase { - public void Execute(CustomFormatPipelineContext context, IServiceConfiguration config) + public void Execute(CustomFormatPipelineContext context) { var transactions = new CustomFormatTransactionData(); @@ -21,7 +22,7 @@ public class CustomFormatTransactionPhase(ILogger log) : ITransactionPipelinePha var serviceCf = FindServiceCfByName(context.ApiFetchOutput, guideCf.Name); if (serviceCf is not null) { - ProcessExistingCf(config, guideCf, serviceCf, transactions); + ProcessExistingCf(guideCf, serviceCf, transactions); continue; } @@ -52,7 +53,6 @@ public class CustomFormatTransactionPhase(ILogger log) : ITransactionPipelinePha } private void ProcessExistingCf( - IServiceConfiguration config, CustomFormatData guideCf, CustomFormatData serviceCf, CustomFormatTransactionData transactions) diff --git a/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs b/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs index 0cfc4421..69db4e72 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/GenericSyncPipeline.cs @@ -3,10 +3,14 @@ using Recyclarr.Config.Models; namespace Recyclarr.Cli.Pipelines.Generic; -public class GenericSyncPipeline(ILogger log, GenericPipelinePhases phases) : ISyncPipeline +public class GenericSyncPipeline( + ILogger log, + GenericPipelinePhases phases, + IServiceConfiguration config +) : ISyncPipeline where TContext : IPipelineContext, new() { - public async Task Execute(ISyncSettings settings, IServiceConfiguration config) + public async Task Execute(ISyncSettings settings) { var context = new TContext(); if (!context.SupportedServiceTypes.Contains(config.ServiceType)) @@ -16,14 +20,14 @@ public class GenericSyncPipeline(ILogger log, GenericPipelinePhases(ILogger log, GenericPipelinePhases where TContext : IPipelineContext { - Task Execute(TContext context, IServiceConfiguration config); + Task Execute(TContext context); } diff --git a/src/Recyclarr.Cli/Pipelines/Generic/IApiPersistencePipelinePhase.cs b/src/Recyclarr.Cli/Pipelines/Generic/IApiPersistencePipelinePhase.cs index 52733d4e..30b0cff1 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/IApiPersistencePipelinePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/IApiPersistencePipelinePhase.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Cli.Pipelines.Generic; public interface IApiPersistencePipelinePhase where TContext : IPipelineContext { - Task Execute(TContext context, IServiceConfiguration config); + Task Execute(TContext context); } diff --git a/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs b/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs index e00c11cb..b1dcc361 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/IConfigPipelinePhase.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Cli.Pipelines.Generic; public interface IConfigPipelinePhase where TContext : IPipelineContext { - Task Execute(TContext context, IServiceConfiguration config); + Task Execute(TContext context); } diff --git a/src/Recyclarr.Cli/Pipelines/Generic/ITransactionPipelinePhase.cs b/src/Recyclarr.Cli/Pipelines/Generic/ITransactionPipelinePhase.cs index 61411c26..59b1aa17 100644 --- a/src/Recyclarr.Cli/Pipelines/Generic/ITransactionPipelinePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/Generic/ITransactionPipelinePhase.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Cli.Pipelines.Generic; public interface ITransactionPipelinePhase where TContext : IPipelineContext { - void Execute(TContext context, IServiceConfiguration config); + void Execute(TContext context); } diff --git a/src/Recyclarr.Cli/Pipelines/ISyncPipeline.cs b/src/Recyclarr.Cli/Pipelines/ISyncPipeline.cs index e972358a..cfd961c9 100644 --- a/src/Recyclarr.Cli/Pipelines/ISyncPipeline.cs +++ b/src/Recyclarr.Cli/Pipelines/ISyncPipeline.cs @@ -1,9 +1,8 @@ using Recyclarr.Cli.Console.Settings; -using Recyclarr.Config.Models; namespace Recyclarr.Cli.Pipelines; public interface ISyncPipeline { - public Task Execute(ISyncSettings settings, IServiceConfiguration config); + public Task Execute(ISyncSettings settings); } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/IServiceBasedMediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/IServiceBasedMediaNamingConfigPhase.cs index 64d0cad6..eec74a62 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/IServiceBasedMediaNamingConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/IServiceBasedMediaNamingConfigPhase.cs @@ -1,4 +1,3 @@ -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; using Recyclarr.TrashGuide.MediaNaming; @@ -6,8 +5,5 @@ namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; public interface IServiceBasedMediaNamingConfigPhase { - Task ProcessNaming( - IServiceConfiguration config, - IMediaNamingGuideService guide, - NamingFormatLookup lookup); + Task ProcessNaming(IMediaNamingGuideService guide, NamingFormatLookup lookup); } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/RadarrMediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/RadarrMediaNamingConfigPhase.cs index 15275d11..c679a653 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/RadarrMediaNamingConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/RadarrMediaNamingConfigPhase.cs @@ -4,12 +4,9 @@ using Recyclarr.TrashGuide.MediaNaming; namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; -public class RadarrMediaNamingConfigPhase : ServiceBasedMediaNamingConfigPhase +public class RadarrMediaNamingConfigPhase(RadarrConfiguration config) : IServiceBasedMediaNamingConfigPhase { - protected override Task ProcessNaming( - RadarrConfiguration config, - IMediaNamingGuideService guide, - NamingFormatLookup lookup) + public Task ProcessNaming(IMediaNamingGuideService guide, NamingFormatLookup lookup) { var guideData = guide.GetRadarrNamingData(); var configData = config.MediaNaming; diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/ServiceBasedMediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/ServiceBasedMediaNamingConfigPhase.cs deleted file mode 100644 index e511341b..00000000 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/ServiceBasedMediaNamingConfigPhase.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Recyclarr.Config.Models; -using Recyclarr.ServarrApi.MediaNaming; -using Recyclarr.TrashGuide.MediaNaming; - -namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; - -public abstract class ServiceBasedMediaNamingConfigPhase : IServiceBasedMediaNamingConfigPhase - where TConfig : IServiceConfiguration -{ - public Task ProcessNaming( - IServiceConfiguration config, - IMediaNamingGuideService guide, - NamingFormatLookup lookup) - { - return ProcessNaming((TConfig) config, guide, lookup); - } - - protected abstract Task ProcessNaming( - TConfig config, - IMediaNamingGuideService guide, - NamingFormatLookup lookup); -} diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/SonarrMediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/SonarrMediaNamingConfigPhase.cs index 35cb164d..335e2ee9 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/SonarrMediaNamingConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/Config/SonarrMediaNamingConfigPhase.cs @@ -4,16 +4,13 @@ using Recyclarr.TrashGuide.MediaNaming; namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; -public class SonarrMediaNamingConfigPhase : ServiceBasedMediaNamingConfigPhase +public class SonarrMediaNamingConfigPhase(SonarrConfiguration config) : IServiceBasedMediaNamingConfigPhase { - protected override Task ProcessNaming( - SonarrConfiguration config, - IMediaNamingGuideService guide, - NamingFormatLookup lookup) + public Task ProcessNaming(IMediaNamingGuideService guide, NamingFormatLookup lookup) { var guideData = guide.GetSonarrNamingData(); var configData = config.MediaNaming; - var keySuffix = ":4"; + const string keySuffix = ":4"; return Task.FromResult(new SonarrMediaNamingDto { diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiFetchPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiFetchPhase.cs index ef8b5fb2..33ce848b 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiFetchPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiFetchPhase.cs @@ -1,13 +1,12 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; public class MediaNamingApiFetchPhase(IMediaNamingApiService api) : IApiFetchPipelinePhase { - public async Task Execute(MediaNamingPipelineContext context, IServiceConfiguration config) + public async Task Execute(MediaNamingPipelineContext context) { - context.ApiFetchOutput = await api.GetNaming(config); + context.ApiFetchOutput = await api.GetNaming(); } } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiPersistencePhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiPersistencePhase.cs index 8156d709..afcbf25a 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiPersistencePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingApiPersistencePhase.cs @@ -1,5 +1,4 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; @@ -7,8 +6,8 @@ namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; public class MediaNamingApiPersistencePhase(IMediaNamingApiService api) : IApiPersistencePipelinePhase { - public async Task Execute(MediaNamingPipelineContext context, IServiceConfiguration config) + public async Task Execute(MediaNamingPipelineContext context) { - await api.UpdateNaming(config, context.TransactionOutput); + await api.UpdateNaming(context.TransactionOutput); } } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs index a3cb5a34..e103d719 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingConfigPhase.cs @@ -18,14 +18,15 @@ public record ProcessedNamingConfig public class MediaNamingConfigPhase( IMediaNamingGuideService guide, - IIndex configPhaseStrategyFactory) + IIndex configPhaseStrategyFactory, + IServiceConfiguration config) : IConfigPipelinePhase { - public async Task Execute(MediaNamingPipelineContext context, IServiceConfiguration config) + public async Task Execute(MediaNamingPipelineContext context) { var lookup = new NamingFormatLookup(); var strategy = configPhaseStrategyFactory[config.ServiceType]; - var dto = await strategy.ProcessNaming(config, guide, lookup); + var dto = await strategy.ProcessNaming(guide, lookup); context.ConfigOutput = new ProcessedNamingConfig {Dto = dto, InvalidNaming = lookup.Errors}; } diff --git a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingTransactionPhase.cs b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingTransactionPhase.cs index d48fed2e..4dcc6d0c 100644 --- a/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingTransactionPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/MediaNaming/PipelinePhases/MediaNamingTransactionPhase.cs @@ -1,12 +1,11 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; namespace Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; public class MediaNamingTransactionPhase : ITransactionPipelinePhase { - public void Execute(MediaNamingPipelineContext context, IServiceConfiguration config) + public void Execute(MediaNamingPipelineContext context) { context.TransactionOutput = context.ApiFetchOutput switch { diff --git a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiFetchPhase.cs b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiFetchPhase.cs index 7a43f03e..0aa80f6b 100644 --- a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiFetchPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiFetchPhase.cs @@ -1,5 +1,4 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityProfile; namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; @@ -9,10 +8,10 @@ public record QualityProfileServiceData(IReadOnlyList Profile public class QualityProfileApiFetchPhase(IQualityProfileApiService api) : IApiFetchPipelinePhase { - public async Task Execute(QualityProfilePipelineContext context, IServiceConfiguration config) + public async Task Execute(QualityProfilePipelineContext context) { - var profiles = await api.GetQualityProfiles(config); - var schema = await api.GetSchema(config); + var profiles = await api.GetQualityProfiles(); + var schema = await api.GetSchema(); context.ApiFetchOutput = new QualityProfileServiceData(profiles.AsReadOnly(), schema); } } diff --git a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiPersistencePhase.cs b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiPersistencePhase.cs index 159c516c..bc4d9ba3 100644 --- a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiPersistencePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileApiPersistencePhase.cs @@ -1,6 +1,5 @@ using Recyclarr.Cli.Pipelines.Generic; using Recyclarr.Cli.Pipelines.QualityProfile.Models; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityProfile; namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; @@ -8,7 +7,7 @@ namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; public class QualityProfileApiPersistencePhase(IQualityProfileApiService api) : IApiPersistencePipelinePhase { - public async Task Execute(QualityProfilePipelineContext context, IServiceConfiguration config) + public async Task Execute(QualityProfilePipelineContext context) { var changedProfiles = context.TransactionOutput.ChangedProfiles; foreach (var profile in changedProfiles.Select(x => x.Profile)) @@ -18,11 +17,11 @@ public class QualityProfileApiPersistencePhase(IQualityProfileApiService api) switch (profile.UpdateReason) { case QualityProfileUpdateReason.New: - await api.CreateQualityProfile(config, dto); + await api.CreateQualityProfile(dto); break; case QualityProfileUpdateReason.Changed: - await api.UpdateQualityProfile(config, dto); + await api.UpdateQualityProfile(dto); break; default: diff --git a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs index e180d5a8..d9d42bd3 100644 --- a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhase.cs @@ -7,10 +7,10 @@ using Recyclarr.TrashGuide.CustomFormat; namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; -public class QualityProfileConfigPhase(ILogger log, ProcessedCustomFormatCache cache) +public class QualityProfileConfigPhase(ILogger log, ProcessedCustomFormatCache cache, IServiceConfiguration config) : IConfigPipelinePhase { - public Task Execute(QualityProfilePipelineContext context, IServiceConfiguration config) + public Task Execute(QualityProfilePipelineContext context) { // 1. For each group of CFs that has a quality profile specified // 2. For each quality profile score config in that CF group diff --git a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhase.cs b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhase.cs index d54c2670..95326f41 100644 --- a/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhase.cs @@ -10,7 +10,7 @@ namespace Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; public class QualityProfileTransactionPhase(QualityProfileStatCalculator statCalculator) : ITransactionPipelinePhase { - public void Execute(QualityProfilePipelineContext context, IServiceConfiguration config) + public void Execute(QualityProfilePipelineContext context) { var transactions = new QualityProfileTransactionData(); diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiFetchPhase.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiFetchPhase.cs index e55dc127..412fec32 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiFetchPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiFetchPhase.cs @@ -1,5 +1,4 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityDefinition; namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; @@ -7,8 +6,8 @@ namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; public class QualitySizeApiFetchPhase(IQualityDefinitionApiService api) : IApiFetchPipelinePhase { - public async Task Execute(QualitySizePipelineContext context, IServiceConfiguration config) + public async Task Execute(QualitySizePipelineContext context) { - context.ApiFetchOutput = await api.GetQualityDefinition(config); + context.ApiFetchOutput = await api.GetQualityDefinition(); } } diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiPersistencePhase.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiPersistencePhase.cs index ae1573e8..4bad4248 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiPersistencePhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeApiPersistencePhase.cs @@ -1,5 +1,4 @@ using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityDefinition; namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; @@ -7,8 +6,8 @@ namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; public class QualitySizeApiPersistencePhase(IQualityDefinitionApiService api) : IApiPersistencePipelinePhase { - public async Task Execute(QualitySizePipelineContext context, IServiceConfiguration config) + public async Task Execute(QualitySizePipelineContext context) { - await api.UpdateQualityDefinition(config, context.TransactionOutput); + await api.UpdateQualityDefinition(context.TransactionOutput); } } diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs index 09933c5b..fcb2062c 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhase.cs @@ -5,10 +5,10 @@ using Recyclarr.TrashGuide.QualitySize; namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; -public class QualitySizeConfigPhase(ILogger log, IQualitySizeGuideService guide) +public class QualitySizeConfigPhase(ILogger log, IQualitySizeGuideService guide, IServiceConfiguration config) : IConfigPipelinePhase { - public Task Execute(QualitySizePipelineContext context, IServiceConfiguration config) + public Task Execute(QualitySizePipelineContext context) { var qualityDef = config.QualityDefinition; if (qualityDef is null) @@ -32,9 +32,9 @@ public class QualitySizeConfigPhase(ILogger log, IQualitySizeGuideService guide) return Task.CompletedTask; } - private void AdjustPreferredRatio(QualityDefinitionConfig config, QualitySizeData selectedQuality) + private void AdjustPreferredRatio(QualityDefinitionConfig qualityDefConfig, QualitySizeData selectedQuality) { - if (config.PreferredRatio is null) + if (qualityDefConfig.PreferredRatio is null) { return; } @@ -42,20 +42,20 @@ public class QualitySizeConfigPhase(ILogger log, IQualitySizeGuideService guide) log.Information("Using an explicit preferred ratio which will override values from the guide"); // Fix an out of range ratio and warn the user - if (config.PreferredRatio is < 0 or > 1) + if (qualityDefConfig.PreferredRatio is < 0 or > 1) { - var clampedRatio = Math.Clamp(config.PreferredRatio.Value, 0, 1); + var clampedRatio = Math.Clamp(qualityDefConfig.PreferredRatio.Value, 0, 1); log.Warning("Your `preferred_ratio` of {CurrentRatio} is out of range. " + "It must be a decimal between 0.0 and 1.0. It has been clamped to {ClampedRatio}", - config.PreferredRatio, clampedRatio); + qualityDefConfig.PreferredRatio, clampedRatio); - config.PreferredRatio = clampedRatio; + qualityDefConfig.PreferredRatio = clampedRatio; } // Apply a calculated preferred size foreach (var quality in selectedQuality.Qualities) { - quality.Preferred = quality.InterpolatedPreferred(config.PreferredRatio.Value); + quality.Preferred = quality.InterpolatedPreferred(qualityDefConfig.PreferredRatio.Value); } } } diff --git a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhase.cs b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhase.cs index 1e3a05f7..4db1b58e 100644 --- a/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhase.cs +++ b/src/Recyclarr.Cli/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhase.cs @@ -1,6 +1,5 @@ using System.Collections.ObjectModel; using Recyclarr.Cli.Pipelines.Generic; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityDefinition; using Recyclarr.TrashGuide.QualitySize; @@ -8,7 +7,7 @@ namespace Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; public class QualitySizeTransactionPhase(ILogger log) : ITransactionPipelinePhase { - public void Execute(QualitySizePipelineContext context, IServiceConfiguration config) + public void Execute(QualitySizePipelineContext context) { // Do not check ConfigOutput for null since the LogPhase does it for us var guideQuality = context.ConfigOutput!.Qualities; diff --git a/src/Recyclarr.Cli/Processors/Delete/DeleteCustomFormatsProcessor.cs b/src/Recyclarr.Cli/Processors/Delete/DeleteCustomFormatsProcessor.cs index b7ba5d51..090f371f 100644 --- a/src/Recyclarr.Cli/Processors/Delete/DeleteCustomFormatsProcessor.cs +++ b/src/Recyclarr.Cli/Processors/Delete/DeleteCustomFormatsProcessor.cs @@ -1,4 +1,6 @@ using System.Diagnostics.CodeAnalysis; +using Autofac; +using JetBrains.Annotations; using Recyclarr.Cli.Console; using Recyclarr.Cli.Console.Settings; using Recyclarr.Config; @@ -9,18 +11,24 @@ using Spectre.Console; namespace Recyclarr.Cli.Processors.Delete; +[UsedImplicitly] +internal class CustomFormatConfigurationScope(ILifetimeScope scope) : ConfigurationScope(scope) +{ + public ICustomFormatApiService CustomFormatApi { get; } = scope.Resolve(); +} + public class DeleteCustomFormatsProcessor( ILogger log, IAnsiConsole console, - ICustomFormatApiService api, - IConfigurationRegistry configRegistry) + IConfigurationRegistry configRegistry, + ConfigurationScopeFactory scopeFactory) : IDeleteCustomFormatsProcessor { public async Task Process(IDeleteCustomFormatSettings settings) { - var config = GetTargetConfig(settings); + using var scope = scopeFactory.Start(GetTargetConfig(settings)); - var cfs = await ObtainCustomFormats(config); + var cfs = await ObtainCustomFormats(scope.CustomFormatApi); if (!settings.All) { @@ -53,11 +61,11 @@ public class DeleteCustomFormatsProcessor( return; } - await DeleteCustomFormats(cfs, config); + await DeleteCustomFormats(scope.CustomFormatApi, cfs); } [SuppressMessage("Design", "CA1031:Do not catch general exception types")] - private async Task DeleteCustomFormats(ICollection cfs, IServiceConfiguration config) + private async Task DeleteCustomFormats(ICustomFormatApiService api, ICollection cfs) { await console.Progress().StartAsync(async ctx => { @@ -68,7 +76,7 @@ public class DeleteCustomFormatsProcessor( { try { - await api.DeleteCustomFormat(config, cf.Id, token); + await api.DeleteCustomFormat(cf.Id, token); log.Debug("Deleted {Name}", cf.Name); } catch (Exception e) @@ -82,13 +90,13 @@ public class DeleteCustomFormatsProcessor( }); } - private async Task> ObtainCustomFormats(IServiceConfiguration config) + private async Task> ObtainCustomFormats(ICustomFormatApiService api) { IList cfs = new List(); await console.Status().StartAsync("Obtaining custom formats...", async _ => { - cfs = await api.GetCustomFormats(config); + cfs = await api.GetCustomFormats(); }); return cfs; diff --git a/src/Recyclarr.Cli/Processors/Sync/SyncPipelineExecutor.cs b/src/Recyclarr.Cli/Processors/Sync/SyncPipelineExecutor.cs index 86c75c9c..0f54cec9 100644 --- a/src/Recyclarr.Cli/Processors/Sync/SyncPipelineExecutor.cs +++ b/src/Recyclarr.Cli/Processors/Sync/SyncPipelineExecutor.cs @@ -1,16 +1,25 @@ using Recyclarr.Cli.Console.Settings; using Recyclarr.Cli.Pipelines; +using Recyclarr.Compatibility; using Recyclarr.Config.Models; +using Spectre.Console; namespace Recyclarr.Cli.Processors.Sync; public class SyncPipelineExecutor( ILogger log, + IAnsiConsole console, IOrderedEnumerable pipelines, - IEnumerable caches) + IEnumerable caches, + ServiceAgnosticCapabilityEnforcer enforcer, + IServiceConfiguration config) { - public async Task Process(ISyncSettings settings, IServiceConfiguration config) + public async Task Process(ISyncSettings settings) { + PrintProcessingHeader(); + + await enforcer.Check(config); + foreach (var cache in caches) { cache.Clear(); @@ -19,7 +28,25 @@ public class SyncPipelineExecutor( foreach (var pipeline in pipelines) { log.Debug("Executing Pipeline: {Pipeline}", pipeline.GetType().Name); - await pipeline.Execute(settings, config); + await pipeline.Execute(settings); } + + log.Information("Completed at {Date}", DateTime.Now); + } + + private void PrintProcessingHeader() + { + var instanceName = config.InstanceName; + + console.WriteLine( + $""" + + =========================================== + Processing {config.ServiceType} Server: [{instanceName}] + =========================================== + + """); + + log.Debug("Processing {Server} server {Name}", config.ServiceType, instanceName); } } diff --git a/src/Recyclarr.Cli/Processors/Sync/SyncProcessor.cs b/src/Recyclarr.Cli/Processors/Sync/SyncProcessor.cs index 5de9a354..2c1e6e2f 100644 --- a/src/Recyclarr.Cli/Processors/Sync/SyncProcessor.cs +++ b/src/Recyclarr.Cli/Processors/Sync/SyncProcessor.cs @@ -1,21 +1,21 @@ using System.Diagnostics.CodeAnalysis; +using Autofac; using Recyclarr.Cli.Console.Settings; using Recyclarr.Cli.Processors.ErrorHandling; -using Recyclarr.Compatibility; using Recyclarr.Config; using Recyclarr.Config.Models; -using Recyclarr.TrashGuide; -using Spectre.Console; namespace Recyclarr.Cli.Processors.Sync; +public class SyncBasedConfigurationScope(ILifetimeScope scope) : ConfigurationScope(scope) +{ + public SyncPipelineExecutor Pipelines { get; } = scope.Resolve(); +} + [SuppressMessage("Design", "CA1031:Do not catch general exception types")] public class SyncProcessor( - IAnsiConsole console, - ILogger log, IConfigurationRegistry configRegistry, - SyncPipelineExecutor pipelines, - ServiceAgnosticCapabilityEnforcer capabilityEnforcer, + ConfigurationScopeFactory configScopeFactory, ConsoleExceptionHandler exceptionHandler) : ISyncProcessor { @@ -55,10 +55,8 @@ public class SyncProcessor( { try { - PrintProcessingHeader(config.ServiceType, config); - await capabilityEnforcer.Check(config); - await pipelines.Process(settings, config); - log.Information("Completed at {Date}", DateTime.Now); + using var scope = configScopeFactory.Start(config); + await scope.Pipelines.Process(settings); } catch (Exception e) { @@ -74,20 +72,4 @@ public class SyncProcessor( return failureDetected; } - - private void PrintProcessingHeader(SupportedServices serviceType, IServiceConfiguration config) - { - var instanceName = config.InstanceName; - - console.WriteLine( - $""" - - =========================================== - Processing {serviceType} Server: [{instanceName}] - =========================================== - - """); - - log.Debug("Processing {Server} server {Name}", serviceType, instanceName); - } } diff --git a/src/Recyclarr.Compatibility/IServiceInformation.cs b/src/Recyclarr.Compatibility/IServiceInformation.cs index f061dd67..969a3740 100644 --- a/src/Recyclarr.Compatibility/IServiceInformation.cs +++ b/src/Recyclarr.Compatibility/IServiceInformation.cs @@ -1,8 +1,6 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility; public interface IServiceInformation { - public Task GetVersion(IServiceConfiguration config); + public Task GetVersion(); } diff --git a/src/Recyclarr.Compatibility/Radarr/IRadarrCapabilityFetcher.cs b/src/Recyclarr.Compatibility/Radarr/IRadarrCapabilityFetcher.cs index 30956d15..62b33f52 100644 --- a/src/Recyclarr.Compatibility/Radarr/IRadarrCapabilityFetcher.cs +++ b/src/Recyclarr.Compatibility/Radarr/IRadarrCapabilityFetcher.cs @@ -1,8 +1,6 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility.Radarr; public interface IRadarrCapabilityFetcher { - Task GetCapabilities(IServiceConfiguration config); + Task GetCapabilities(); } diff --git a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityEnforcer.cs b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityEnforcer.cs index f5415737..a6d64d7f 100644 --- a/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityEnforcer.cs +++ b/src/Recyclarr.Compatibility/Radarr/RadarrCapabilityEnforcer.cs @@ -1,12 +1,10 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility.Radarr; public class RadarrCapabilityEnforcer(IRadarrCapabilityFetcher capabilityFetcher) { - public async Task Check(RadarrConfiguration config) + public async Task Check() { - _ = await capabilityFetcher.GetCapabilities(config); + _ = await capabilityFetcher.GetCapabilities(); // For the future: Add more capability checks here as needed } diff --git a/src/Recyclarr.Compatibility/ServiceAgnosticCapabilityEnforcer.cs b/src/Recyclarr.Compatibility/ServiceAgnosticCapabilityEnforcer.cs index 71132e13..c11f0f60 100644 --- a/src/Recyclarr.Compatibility/ServiceAgnosticCapabilityEnforcer.cs +++ b/src/Recyclarr.Compatibility/ServiceAgnosticCapabilityEnforcer.cs @@ -12,12 +12,12 @@ public class ServiceAgnosticCapabilityEnforcer( { switch (config) { - case SonarrConfiguration c: - await sonarrEnforcer.Check(c); + case SonarrConfiguration: + await sonarrEnforcer.Check(); break; - case RadarrConfiguration c: - await radarrEnforcer.Check(c); + case RadarrConfiguration: + await radarrEnforcer.Check(); break; } } diff --git a/src/Recyclarr.Compatibility/ServiceCapabilityFetcher.cs b/src/Recyclarr.Compatibility/ServiceCapabilityFetcher.cs index b115dc83..e141d50b 100644 --- a/src/Recyclarr.Compatibility/ServiceCapabilityFetcher.cs +++ b/src/Recyclarr.Compatibility/ServiceCapabilityFetcher.cs @@ -1,13 +1,11 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility; public abstract class ServiceCapabilityFetcher(IServiceInformation info) where T : class { - public async Task GetCapabilities(IServiceConfiguration config) + public async Task GetCapabilities() { - var version = await info.GetVersion(config); + var version = await info.GetVersion(); return BuildCapabilitiesObject(version); } diff --git a/src/Recyclarr.Compatibility/ServiceInformation.cs b/src/Recyclarr.Compatibility/ServiceInformation.cs index 521d4068..46c81f78 100644 --- a/src/Recyclarr.Compatibility/ServiceInformation.cs +++ b/src/Recyclarr.Compatibility/ServiceInformation.cs @@ -1,5 +1,4 @@ using Flurl.Http; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.System; using Serilog; @@ -7,11 +6,11 @@ namespace Recyclarr.Compatibility; public class ServiceInformation(ISystemApiService api, ILogger log) : IServiceInformation { - public async Task GetVersion(IServiceConfiguration config) + public async Task GetVersion() { try { - var status = await api.GetStatus(config); + var status = await api.GetStatus(); log.Debug("{Service} Version: {Version}", status.AppName, status.Version); return new Version(status.Version); } diff --git a/src/Recyclarr.Compatibility/Sonarr/ISonarrCapabilityFetcher.cs b/src/Recyclarr.Compatibility/Sonarr/ISonarrCapabilityFetcher.cs index b893172e..e23644d9 100644 --- a/src/Recyclarr.Compatibility/Sonarr/ISonarrCapabilityFetcher.cs +++ b/src/Recyclarr.Compatibility/Sonarr/ISonarrCapabilityFetcher.cs @@ -1,8 +1,6 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility.Sonarr; public interface ISonarrCapabilityFetcher { - Task GetCapabilities(IServiceConfiguration config); + Task GetCapabilities(); } diff --git a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityEnforcer.cs b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityEnforcer.cs index dbe81987..8d7a7970 100644 --- a/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityEnforcer.cs +++ b/src/Recyclarr.Compatibility/Sonarr/SonarrCapabilityEnforcer.cs @@ -1,12 +1,10 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.Compatibility.Sonarr; public class SonarrCapabilityEnforcer(ISonarrCapabilityFetcher capabilityFetcher) { - public async Task Check(SonarrConfiguration config) + public async Task Check() { - var capabilities = await capabilityFetcher.GetCapabilities(config); + var capabilities = await capabilityFetcher.GetCapabilities(); if (capabilities.Version < SonarrCapabilities.MinimumVersion) { diff --git a/src/Recyclarr.Config/ConfigAutofacModule.cs b/src/Recyclarr.Config/ConfigAutofacModule.cs index 663451ed..25f45899 100644 --- a/src/Recyclarr.Config/ConfigAutofacModule.cs +++ b/src/Recyclarr.Config/ConfigAutofacModule.cs @@ -29,6 +29,7 @@ public class ConfigAutofacModule : Module builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); + builder.RegisterType(); // Config Post Processors builder.RegisterType().As(); diff --git a/src/Recyclarr.Config/ConfigurationScope.cs b/src/Recyclarr.Config/ConfigurationScope.cs new file mode 100644 index 00000000..5e181978 --- /dev/null +++ b/src/Recyclarr.Config/ConfigurationScope.cs @@ -0,0 +1,23 @@ +using System.Diagnostics.CodeAnalysis; +using Autofac; + +namespace Recyclarr.Config; + +[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor", Justification = + "Base types are required to instruct Autofac which types we want to resolve")] +public abstract class ConfigurationScope(ILifetimeScope scope) : IDisposable +{ + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + scope.Dispose(); + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } +} diff --git a/src/Recyclarr.Config/ConfigurationScopeFactory.cs b/src/Recyclarr.Config/ConfigurationScopeFactory.cs new file mode 100644 index 00000000..c20c3a2e --- /dev/null +++ b/src/Recyclarr.Config/ConfigurationScopeFactory.cs @@ -0,0 +1,20 @@ +using Autofac; +using JetBrains.Annotations; +using Recyclarr.Config.Models; + +namespace Recyclarr.Config; + +[UsedImplicitly] +public class ConfigurationScopeFactory(ILifetimeScope scope) +{ + public T Start(IServiceConfiguration config) where T : ConfigurationScope + { + var childScope = scope.BeginLifetimeScope(c => + { + c.RegisterInstance(config).As(config.GetType()).As(); + c.RegisterType(); + }); + + return childScope.Resolve(); + } +} diff --git a/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs b/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs index 664f90ff..65d90ee9 100644 --- a/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs +++ b/src/Recyclarr.ServarrApi/CustomFormat/CustomFormatApiService.cs @@ -1,36 +1,32 @@ using Flurl.Http; -using Recyclarr.Config.Models; using Recyclarr.TrashGuide.CustomFormat; namespace Recyclarr.ServarrApi.CustomFormat; public class CustomFormatApiService(IServarrRequestBuilder service) : ICustomFormatApiService { - public async Task> GetCustomFormats(IServiceConfiguration config) + public async Task> GetCustomFormats() { - return await service.Request(config, "customformat") + return await service.Request("customformat") .GetJsonAsync>(); } - public async Task CreateCustomFormat(IServiceConfiguration config, CustomFormatData cf) + public async Task CreateCustomFormat(CustomFormatData cf) { - return await service.Request(config, "customformat") + return await service.Request("customformat") .PostJsonAsync(cf) .ReceiveJson(); } - public async Task UpdateCustomFormat(IServiceConfiguration config, CustomFormatData cf) + public async Task UpdateCustomFormat(CustomFormatData cf) { - await service.Request(config, "customformat", cf.Id) + await service.Request("customformat", cf.Id) .PutJsonAsync(cf); } - public async Task DeleteCustomFormat( - IServiceConfiguration config, - int customFormatId, - CancellationToken cancellationToken = default) + public async Task DeleteCustomFormat(int customFormatId, CancellationToken cancellationToken = default) { - await service.Request(config, "customformat", customFormatId) + await service.Request("customformat", customFormatId) .DeleteAsync(cancellationToken: cancellationToken); } } diff --git a/src/Recyclarr.ServarrApi/CustomFormat/ICustomFormatApiService.cs b/src/Recyclarr.ServarrApi/CustomFormat/ICustomFormatApiService.cs index 66674833..89754952 100644 --- a/src/Recyclarr.ServarrApi/CustomFormat/ICustomFormatApiService.cs +++ b/src/Recyclarr.ServarrApi/CustomFormat/ICustomFormatApiService.cs @@ -1,16 +1,11 @@ -using Recyclarr.Config.Models; using Recyclarr.TrashGuide.CustomFormat; namespace Recyclarr.ServarrApi.CustomFormat; public interface ICustomFormatApiService { - Task> GetCustomFormats(IServiceConfiguration config); - Task CreateCustomFormat(IServiceConfiguration config, CustomFormatData cf); - Task UpdateCustomFormat(IServiceConfiguration config, CustomFormatData cf); - - Task DeleteCustomFormat( - IServiceConfiguration config, - int customFormatId, - CancellationToken cancellationToken = default); + Task> GetCustomFormats(); + Task CreateCustomFormat(CustomFormatData cf); + Task UpdateCustomFormat(CustomFormatData cf); + Task DeleteCustomFormat(int customFormatId, CancellationToken cancellationToken = default); } diff --git a/src/Recyclarr.ServarrApi/IServarrRequestBuilder.cs b/src/Recyclarr.ServarrApi/IServarrRequestBuilder.cs index 2f99a984..e242633a 100644 --- a/src/Recyclarr.ServarrApi/IServarrRequestBuilder.cs +++ b/src/Recyclarr.ServarrApi/IServarrRequestBuilder.cs @@ -1,9 +1,8 @@ using Flurl.Http; -using Recyclarr.Config.Models; namespace Recyclarr.ServarrApi; public interface IServarrRequestBuilder { - IFlurlRequest Request(IServiceConfiguration config, params object[] path); + IFlurlRequest Request(params object[] path); } diff --git a/src/Recyclarr.ServarrApi/MediaNaming/IMediaNamingApiService.cs b/src/Recyclarr.ServarrApi/MediaNaming/IMediaNamingApiService.cs index c280683a..a8602f4e 100644 --- a/src/Recyclarr.ServarrApi/MediaNaming/IMediaNamingApiService.cs +++ b/src/Recyclarr.ServarrApi/MediaNaming/IMediaNamingApiService.cs @@ -1,9 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.ServarrApi.MediaNaming; public interface IMediaNamingApiService { - Task GetNaming(IServiceConfiguration config); - Task UpdateNaming(IServiceConfiguration config, MediaNamingDto dto); + Task GetNaming(); + Task UpdateNaming(MediaNamingDto dto); } diff --git a/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs b/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs index ce933b97..f338c2f1 100644 --- a/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs +++ b/src/Recyclarr.ServarrApi/MediaNaming/MediaNamingApiService.cs @@ -4,13 +4,12 @@ using Recyclarr.TrashGuide; namespace Recyclarr.ServarrApi.MediaNaming; -public class MediaNamingApiService(IServarrRequestBuilder service) : IMediaNamingApiService +public class MediaNamingApiService(IServarrRequestBuilder service, IServiceConfiguration config) + : IMediaNamingApiService { - public async Task GetNaming(IServiceConfiguration config) + public async Task GetNaming() { - var response = await service.Request(config, "config", "naming") - .GetAsync(); - + var response = await service.Request("config", "naming").GetAsync(); return config.ServiceType switch { SupportedServices.Radarr => await response.GetJsonAsync(), @@ -19,9 +18,9 @@ public class MediaNamingApiService(IServarrRequestBuilder service) : IMediaNamin }; } - public async Task UpdateNaming(IServiceConfiguration config, MediaNamingDto dto) + public async Task UpdateNaming(MediaNamingDto dto) { - await service.Request(config, "config", "naming") + await service.Request("config", "naming") .PutJsonAsync(dto); } } diff --git a/src/Recyclarr.ServarrApi/QualityDefinition/IQualityDefinitionApiService.cs b/src/Recyclarr.ServarrApi/QualityDefinition/IQualityDefinitionApiService.cs index de20deb8..30f1ddd6 100644 --- a/src/Recyclarr.ServarrApi/QualityDefinition/IQualityDefinitionApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityDefinition/IQualityDefinitionApiService.cs @@ -1,12 +1,7 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.ServarrApi.QualityDefinition; public interface IQualityDefinitionApiService { - Task> GetQualityDefinition(IServiceConfiguration config); - - Task> UpdateQualityDefinition( - IServiceConfiguration config, - IList newQuality); + Task> GetQualityDefinition(); + Task> UpdateQualityDefinition(IList newQuality); } diff --git a/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs b/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs index f4dcfd3b..17e07211 100644 --- a/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityDefinition/QualityDefinitionApiService.cs @@ -1,21 +1,19 @@ using Flurl.Http; -using Recyclarr.Config.Models; namespace Recyclarr.ServarrApi.QualityDefinition; internal class QualityDefinitionApiService(IServarrRequestBuilder service) : IQualityDefinitionApiService { - public async Task> GetQualityDefinition(IServiceConfiguration config) + public async Task> GetQualityDefinition() { - return await service.Request(config, "qualitydefinition") + return await service.Request("qualitydefinition") .GetJsonAsync>(); } public async Task> UpdateQualityDefinition( - IServiceConfiguration config, IList newQuality) { - return await service.Request(config, "qualityDefinition", "update") + return await service.Request("qualityDefinition", "update") .PutJsonAsync(newQuality) .ReceiveJson>(); } diff --git a/src/Recyclarr.ServarrApi/QualityProfile/IQualityProfileApiService.cs b/src/Recyclarr.ServarrApi/QualityProfile/IQualityProfileApiService.cs index 9b62574f..4dbd232f 100644 --- a/src/Recyclarr.ServarrApi/QualityProfile/IQualityProfileApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityProfile/IQualityProfileApiService.cs @@ -1,11 +1,9 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.ServarrApi.QualityProfile; public interface IQualityProfileApiService { - Task> GetQualityProfiles(IServiceConfiguration config); - Task UpdateQualityProfile(IServiceConfiguration config, QualityProfileDto profile); - Task GetSchema(IServiceConfiguration config); - Task CreateQualityProfile(IServiceConfiguration config, QualityProfileDto profile); + Task> GetQualityProfiles(); + Task UpdateQualityProfile(QualityProfileDto profile); + Task GetSchema(); + Task CreateQualityProfile(QualityProfileDto profile); } diff --git a/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs b/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs index 873aa41f..75074ef0 100644 --- a/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs +++ b/src/Recyclarr.ServarrApi/QualityProfile/QualityProfileApiService.cs @@ -1,40 +1,39 @@ using Flurl.Http; -using Recyclarr.Config.Models; namespace Recyclarr.ServarrApi.QualityProfile; internal class QualityProfileApiService(IServarrRequestBuilder service) : IQualityProfileApiService { - public async Task> GetQualityProfiles(IServiceConfiguration config) + public async Task> GetQualityProfiles() { - var response = await service.Request(config, "qualityprofile") + var response = await service.Request("qualityprofile") .GetJsonAsync>(); return response.Select(x => x.ReverseItems()).ToList(); } - public async Task GetSchema(IServiceConfiguration config) + public async Task GetSchema() { - var response = await service.Request(config, "qualityprofile", "schema") + var response = await service.Request("qualityprofile", "schema") .GetJsonAsync(); return response.ReverseItems(); } - public async Task UpdateQualityProfile(IServiceConfiguration config, QualityProfileDto profile) + public async Task UpdateQualityProfile(QualityProfileDto profile) { if (profile.Id is null) { throw new ArgumentException($"Profile's ID property must not be null: {profile.Name}"); } - await service.Request(config, "qualityprofile", profile.Id) + await service.Request("qualityprofile", profile.Id) .PutJsonAsync(profile.ReverseItems()); } - public async Task CreateQualityProfile(IServiceConfiguration config, QualityProfileDto profile) + public async Task CreateQualityProfile(QualityProfileDto profile) { - var response = await service.Request(config, "qualityprofile") + var response = await service.Request("qualityprofile") .PostJsonAsync(profile.ReverseItems()) .ReceiveJson(); diff --git a/src/Recyclarr.ServarrApi/ServarrApiAutofacModule.cs b/src/Recyclarr.ServarrApi/ServarrApiAutofacModule.cs index df9f0f0e..0e7038d8 100644 --- a/src/Recyclarr.ServarrApi/ServarrApiAutofacModule.cs +++ b/src/Recyclarr.ServarrApi/ServarrApiAutofacModule.cs @@ -12,11 +12,20 @@ public class ServarrApiAutofacModule : Module protected override void Load(ContainerBuilder builder) { base.Load(builder); - builder.RegisterType().As(); + + // This is used by all specific API service classes registered below. builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); + + builder.RegisterType().As() + .InstancePerLifetimeScope(); + + builder.RegisterType().As() + .InstancePerLifetimeScope(); + builder.RegisterType().As() + .InstancePerLifetimeScope(); + builder.RegisterType().As() + .InstancePerLifetimeScope(); + builder.RegisterType().As() + .InstancePerLifetimeScope(); } } diff --git a/src/Recyclarr.ServarrApi/ServarrRequestBuilder.cs b/src/Recyclarr.ServarrApi/ServarrRequestBuilder.cs index d8414bfe..f42bb621 100644 --- a/src/Recyclarr.ServarrApi/ServarrRequestBuilder.cs +++ b/src/Recyclarr.ServarrApi/ServarrRequestBuilder.cs @@ -14,10 +14,11 @@ public class ServarrRequestBuilder( ILogger log, IFlurlClientCache clientCache, ISettingsProvider settingsProvider, - IEnumerable eventHandlers) + IEnumerable eventHandlers, + IServiceConfiguration config) : IServarrRequestBuilder { - public IFlurlRequest Request(IServiceConfiguration config, params object[] path) + public IFlurlRequest Request(params object[] path) { var client = clientCache.GetOrAdd( config.InstanceName, @@ -42,16 +43,16 @@ public class ServarrRequestBuilder( settings.JsonSerializer = new DefaultJsonSerializer(GlobalJsonSerializerSettings.Services); }); - builder.ConfigureInnerHandler(handler => + if (!settingsProvider.Settings.EnableSslCertificateValidation) { - if (!settingsProvider.Settings.EnableSslCertificateValidation) + builder.ConfigureInnerHandler(handler => { log.Warning( "Security Risk: Certificate validation is being DISABLED because setting " + "`enable_ssl_certificate_validation` is set to `false`"); handler.ServerCertificateCustomValidationCallback = (_, _, _, _) => true; - } - }); + }); + } } } diff --git a/src/Recyclarr.ServarrApi/System/ISystemApiService.cs b/src/Recyclarr.ServarrApi/System/ISystemApiService.cs index c719f0c7..35ec87ed 100644 --- a/src/Recyclarr.ServarrApi/System/ISystemApiService.cs +++ b/src/Recyclarr.ServarrApi/System/ISystemApiService.cs @@ -1,8 +1,6 @@ -using Recyclarr.Config.Models; - namespace Recyclarr.ServarrApi.System; public interface ISystemApiService { - Task GetStatus(IServiceConfiguration config); + Task GetStatus(); } diff --git a/src/Recyclarr.ServarrApi/System/SystemApiService.cs b/src/Recyclarr.ServarrApi/System/SystemApiService.cs index cb8b990d..699ac821 100644 --- a/src/Recyclarr.ServarrApi/System/SystemApiService.cs +++ b/src/Recyclarr.ServarrApi/System/SystemApiService.cs @@ -1,13 +1,12 @@ using Flurl.Http; -using Recyclarr.Config.Models; namespace Recyclarr.ServarrApi.System; public class SystemApiService(IServarrRequestBuilder service) : ISystemApiService { - public async Task GetStatus(IServiceConfiguration config) + public async Task GetStatus() { - return await service.Request(config, "system", "status") + return await service.Request("system", "status") .GetJsonAsync(); } } diff --git a/tests/Recyclarr.Cli.IntegrationTests/CompositionRootTest.cs b/tests/Recyclarr.Cli.IntegrationTests/CompositionRootTest.cs index 323f2fd3..9022b850 100644 --- a/tests/Recyclarr.Cli.IntegrationTests/CompositionRootTest.cs +++ b/tests/Recyclarr.Cli.IntegrationTests/CompositionRootTest.cs @@ -1,8 +1,8 @@ using System.Collections; -using System.Diagnostics.CodeAnalysis; using Autofac; using Autofac.Core; using NUnit.Framework.Internal; +using Recyclarr.Config.Models; using Recyclarr.Platform; using Recyclarr.TestLibrary.Autofac; using Serilog.Core; @@ -13,9 +13,6 @@ namespace Recyclarr.Cli.IntegrationTests; [TestFixture] public class CompositionRootTest { - // Warning CA1812 : CompositionRootTest.ConcreteTypeEnumerator is an internal class that is apparently never - // instantiated. - [SuppressMessage("Performance", "CA1812", Justification = "Created via reflection by TestCaseSource attribute")] private sealed class ConcreteTypeEnumerator : IEnumerable { public IEnumerator GetEnumerator() @@ -28,6 +25,11 @@ public class CompositionRootTest // in the CompositionRoot. Register mocks/stubs here. builder.RegisterMockFor(); + // Normally in per-instance syncing, a child lifetime scope is created to register IServiceConfiguration. + // However, in the test for checking whether all necessary dependencies are registered, we provide a mock + // registration here for the purposes of getting the test to pass. + builder.RegisterMockFor(); + var container = builder.Build(); return container.ComponentRegistry.Registrations .SelectMany(x => x.Services) diff --git a/tests/Recyclarr.Cli.IntegrationTests/CustomFormatTransactionPhaseTest.cs b/tests/Recyclarr.Cli.IntegrationTests/CustomFormatTransactionPhaseTest.cs index f35def9e..b3e271cf 100644 --- a/tests/Recyclarr.Cli.IntegrationTests/CustomFormatTransactionPhaseTest.cs +++ b/tests/Recyclarr.Cli.IntegrationTests/CustomFormatTransactionPhaseTest.cs @@ -2,6 +2,7 @@ using Recyclarr.Cli.Pipelines.CustomFormat; using Recyclarr.Cli.Pipelines.CustomFormat.Cache; using Recyclarr.Cli.Pipelines.CustomFormat.Models; using Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; +using Recyclarr.Config; using Recyclarr.Tests.TestLibrary; using Recyclarr.TrashGuide.CustomFormat; @@ -13,9 +14,9 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Add_new_cf() { - var sut = Resolve(); - - var config = NewConfig.Radarr(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr()); + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -24,7 +25,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("one", "cf1")] }; - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -38,7 +39,9 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Update_cf_by_matching_name() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr()); + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -56,9 +59,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ] }; - var config = NewConfig.Radarr(); - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -75,7 +76,9 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Update_cf_by_matching_id_different_names() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr()); + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -93,9 +96,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ] }; - var config = NewConfig.Radarr(); - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -112,7 +113,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Update_cf_by_matching_id_same_names() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = true + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -130,12 +137,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = true - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -152,7 +154,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Conflicting_cf_when_new_cf_has_name_of_existing() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = false + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -165,12 +173,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("one", "cf1")] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = false - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -184,7 +187,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Conflicting_cf_when_cached_cf_has_name_of_existing() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = false + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -197,12 +206,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("one", "cf1")] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = false - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -216,7 +220,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Updated_cf_with_matching_name_and_id() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = false + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -238,12 +248,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = false - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -257,7 +262,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Unchanged_cfs_with_replace_enabled() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = true + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -266,12 +277,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("one", "cf1")] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = true - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -282,7 +288,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Unchanged_cfs_without_replace() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + ReplaceExistingCustomFormats = false + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -291,12 +303,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("one", "cf1")] }; - var config = NewConfig.Radarr() with - { - ReplaceExistingCustomFormats = false - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -307,7 +314,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Deleted_cfs_when_enabled() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + DeleteOldCustomFormats = true + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -316,12 +329,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [] }; - var config = NewConfig.Radarr() with - { - DeleteOldCustomFormats = true - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { @@ -335,7 +343,13 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void No_deleted_cfs_when_disabled() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr() with + { + DeleteOldCustomFormats = false + }); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -344,12 +358,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [] }; - var config = NewConfig.Radarr() with - { - DeleteOldCustomFormats = false - }; - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData()); } @@ -357,7 +366,10 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Do_not_delete_cfs_in_config() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr()); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -366,9 +378,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("two", "cf2", 2)] }; - var config = NewConfig.Radarr(); - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.DeletedCustomFormats.Should().BeEmpty(); } @@ -376,7 +386,10 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture [Test] public void Add_new_cf_when_in_cache_but_not_in_service() { - var sut = Resolve(); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(NewConfig.Radarr()); + + var sut = scope.Resolve(); var context = new CustomFormatPipelineContext { @@ -385,9 +398,7 @@ internal class CustomFormatTransactionPhaseTest : CliIntegrationFixture ConfigOutput = [NewCf.Data("two", "cf2", 2)] }; - var config = NewConfig.Radarr(); - - sut.Execute(context, config); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new CustomFormatTransactionData { diff --git a/tests/Recyclarr.Cli.IntegrationTests/MediaNamingConfigPhaseIntegrationTest.cs b/tests/Recyclarr.Cli.IntegrationTests/MediaNamingConfigPhaseIntegrationTest.cs deleted file mode 100644 index 0ed89a93..00000000 --- a/tests/Recyclarr.Cli.IntegrationTests/MediaNamingConfigPhaseIntegrationTest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Autofac.Core.Registration; -using Recyclarr.Cli.Pipelines.MediaNaming; -using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; -using Recyclarr.Config.Models; -using Recyclarr.TrashGuide; - -namespace Recyclarr.Cli.IntegrationTests; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -internal class MediaNamingConfigPhaseIntegrationTest : CliIntegrationFixture -{ - private sealed record UnsupportedConfigType : ServiceConfiguration - { - public override SupportedServices ServiceType => (SupportedServices) 999; - } - - [Test] - public async Task Throw_on_unknown_config_type() - { - var sut = Resolve(); - var act = () => sut.Execute(new MediaNamingPipelineContext(), new UnsupportedConfigType {InstanceName = ""}); - await act.Should().ThrowAsync(); - } -} diff --git a/tests/Recyclarr.Cli.Tests/Cache/CacheStoragePathTest.cs b/tests/Recyclarr.Cli.Tests/Cache/CacheStoragePathTest.cs index 97438709..d814ee30 100644 --- a/tests/Recyclarr.Cli.Tests/Cache/CacheStoragePathTest.cs +++ b/tests/Recyclarr.Cli.Tests/Cache/CacheStoragePathTest.cs @@ -1,3 +1,4 @@ +using AutoFixture; using Recyclarr.Cli.Cache; using Recyclarr.Config.Models; @@ -6,16 +7,19 @@ namespace Recyclarr.Cli.Tests.Cache; [TestFixture] public class CacheStoragePathTest { - [Test, AutoMockData] - public void Use_correct_name_in_path(CacheStoragePath sut) + [Test] + public void Use_correct_name_in_path() { - var config = new SonarrConfiguration + var fixture = NSubstituteFixture.Create(); + + fixture.Inject(new SonarrConfiguration { BaseUrl = new Uri("http://something/foo/bar"), InstanceName = "thename" - }; + }); - var result = sut.CalculatePath(config, "obj"); + var sut = fixture.Create(); + var result = sut.CalculatePath("obj"); result.FullName.Should().MatchRegex(@".*[/\\][a-f0-9]+[/\\]obj\.json$"); } diff --git a/tests/Recyclarr.Cli.Tests/Cache/ServiceCacheTest.cs b/tests/Recyclarr.Cli.Tests/Cache/ServiceCacheTest.cs index 6b67cced..3b02378c 100644 --- a/tests/Recyclarr.Cli.Tests/Cache/ServiceCacheTest.cs +++ b/tests/Recyclarr.Cli.Tests/Cache/ServiceCacheTest.cs @@ -2,7 +2,6 @@ using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using Recyclarr.Cli.Cache; using Recyclarr.Cli.Pipelines.CustomFormat.Cache; -using Recyclarr.Config.Models; namespace Recyclarr.Cli.Tests.Cache; @@ -27,10 +26,9 @@ public class ServiceCacheTest [Test, AutoMockData] public void Load_returns_null_when_file_does_not_exist( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, - IServiceConfiguration config, ServiceCache sut) { - var result = sut.Load(config); + var result = sut.Load(); result.Should().BeNull(); } @@ -38,7 +36,6 @@ public class ServiceCacheTest public void Loading_with_attribute_parses_correctly( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { const string testJson = @@ -49,9 +46,9 @@ public class ServiceCacheTest const string testJsonPath = "cacheFile.json"; fs.AddFile(testJsonPath, new MockFileData(testJson)); - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New(testJsonPath)); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New(testJsonPath)); - var obj = sut.Load(config); + var obj = sut.Load(); obj.Should().NotBeNull(); obj!.TestValue.Should().Be("Foo"); @@ -59,10 +56,9 @@ public class ServiceCacheTest [Test, AutoMockData] public void Loading_with_invalid_object_name_throws( - IServiceConfiguration config, ServiceCache sut) { - Action act = () => sut.Load(config); + Action act = () => sut.Load(); act.Should() .Throw() @@ -71,10 +67,9 @@ public class ServiceCacheTest [Test, AutoMockData] public void Loading_without_attribute_throws( - IServiceConfiguration config, ServiceCache sut) { - Action act = () => sut.Load(config); + Action act = () => sut.Load(); act.Should() .Throw() @@ -85,17 +80,16 @@ public class ServiceCacheTest public void Properties_are_saved_using_snake_case( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { - storage.CalculatePath(default!, default!) + storage.CalculatePath(default!) .ReturnsForAnyArgs(_ => fs.FileInfo.New($"{ValidObjectName}.json")); - sut.Save(new ObjectWithAttribute {TestValue = "Foo"}, config); + sut.Save(new ObjectWithAttribute {TestValue = "Foo"}); fs.AllFiles.Should().ContainMatch($"*{ValidObjectName}.json"); - var file = fs.GetFile(storage.CalculatePath(config, "").FullName); + var file = fs.GetFile(storage.CalculatePath("").FullName); file.Should().NotBeNull(); file.TextContents.Should().Contain("\"test_value\""); } @@ -104,13 +98,12 @@ public class ServiceCacheTest public void Saving_with_attribute_parses_correctly( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { const string testJsonPath = "cacheFile.json"; - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New(testJsonPath)); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New(testJsonPath)); - sut.Save(new ObjectWithAttribute {TestValue = "Foo"}, config); + sut.Save(new ObjectWithAttribute {TestValue = "Foo"}); var expectedFile = fs.GetFile(testJsonPath); expectedFile.Should().NotBeNull(); @@ -124,10 +117,9 @@ public class ServiceCacheTest [Test, AutoMockData] public void Saving_with_invalid_object_name_throws( - IServiceConfiguration config, ServiceCache sut) { - var act = () => sut.Save(new ObjectWithAttributeInvalidChars(), config); + var act = () => sut.Save(new ObjectWithAttributeInvalidChars()); act.Should() .Throw() @@ -136,10 +128,9 @@ public class ServiceCacheTest [Test, AutoMockData] public void Saving_without_attribute_throws( - IServiceConfiguration config, ServiceCache sut) { - var act = () => sut.Save(new ObjectWithoutAttribute(), config); + var act = () => sut.Save(new ObjectWithoutAttribute()); act.Should() .Throw() @@ -150,14 +141,13 @@ public class ServiceCacheTest public void Switching_config_and_base_url_should_yield_different_cache_paths( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New("Foo.json")); - sut.Save(new ObjectWithAttribute {TestValue = "Foo"}, config); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New("Foo.json")); + sut.Save(new ObjectWithAttribute {TestValue = "Foo"}); - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New("Bar.json")); - sut.Save(new ObjectWithAttribute {TestValue = "Bar"}, config); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New("Bar.json")); + sut.Save(new ObjectWithAttribute {TestValue = "Bar"}); var expectedFiles = new[] {"*Foo.json", "*Bar.json"}; foreach (var expectedFile in expectedFiles) @@ -170,13 +160,12 @@ public class ServiceCacheTest public void When_cache_file_is_empty_do_not_throw( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New("cacheFile.json")); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New("cacheFile.json")); fs.AddFile("cacheFile.json", new MockFileData("")); - Action act = () => sut.Load(config); + Action act = () => sut.Load(); act.Should().NotThrow(); } @@ -185,7 +174,6 @@ public class ServiceCacheTest public void Name_properties_are_set_on_load( [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, [Frozen] ICacheStoragePath storage, - IServiceConfiguration config, ServiceCache sut) { const string cacheJson = @@ -203,9 +191,9 @@ public class ServiceCacheTest """; fs.AddFile("cacheFile.json", new MockFileData(cacheJson)); - storage.CalculatePath(default!, default!).ReturnsForAnyArgs(fs.FileInfo.New("cacheFile.json")); + storage.CalculatePath(default!).ReturnsForAnyArgs(fs.FileInfo.New("cacheFile.json")); - var result = sut.Load(config); + var result = sut.Load(); result.Should().BeEquivalentTo(new { diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Cache/CustomFormatCachePersisterTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Cache/CustomFormatCachePersisterTest.cs index 1d9c7f8a..56ce1af3 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Cache/CustomFormatCachePersisterTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Cache/CustomFormatCachePersisterTest.cs @@ -1,7 +1,6 @@ using AutoFixture; using Recyclarr.Cli.Cache; using Recyclarr.Cli.Pipelines.CustomFormat.Cache; -using Recyclarr.Config.Models; namespace Recyclarr.Cli.Tests.Pipelines.CustomFormat.Cache; @@ -16,16 +15,14 @@ public class CustomFormatCachePersisterTest var serviceCache = fixture.Freeze(); var sut = fixture.Create(); - var config = Substitute.For(); - var testCfObj = new CustomFormatCacheData(versionToTest, "", [ new TrashIdMapping("", "", 5) ]); - serviceCache.Load(config).Returns(testCfObj); + serviceCache.Load().Returns(testCfObj); - var act = () => sut.Load(config); + var act = () => sut.Load(); act.Should().Throw(); } @@ -37,16 +34,14 @@ public class CustomFormatCachePersisterTest var serviceCache = fixture.Freeze(); var sut = fixture.Create(); - var config = Substitute.For(); - var testCfObj = new CustomFormatCacheData(CustomFormatCachePersister.LatestVersion, "", [ new TrashIdMapping("", "", 5) ]); - serviceCache.Load(config).Returns(testCfObj); + serviceCache.Load().Returns(testCfObj); - var result = sut.Load(config); + var result = sut.Load(); result.Should().NotBeNull(); } @@ -59,11 +54,10 @@ public class CustomFormatCachePersisterTest var sut = fixture.Create(); TrashIdMapping[] mappings = [new TrashIdMapping("abc", "name", 123)]; - var config = Substitute.For(); - serviceCache.Load(config).Returns(new CustomFormatCacheData(1, "", mappings)); + serviceCache.Load().Returns(new CustomFormatCacheData(1, "", mappings)); - var result = sut.Load(config); + var result = sut.Load(); result.Mappings.Should().BeEquivalentTo(mappings); } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs index 9199ff95..c32037b1 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/CustomFormat/PipelinePhases/CustomFormatConfigPhaseTest.cs @@ -1,3 +1,4 @@ +using AutoFixture; using Recyclarr.Cli.Pipelines.CustomFormat; using Recyclarr.Cli.Pipelines.CustomFormat.PipelinePhases; using Recyclarr.Config.Models; @@ -9,18 +10,19 @@ namespace Recyclarr.Cli.Tests.Pipelines.CustomFormat.PipelinePhases; [TestFixture] public class CustomFormatConfigPhaseTest { - [Test, AutoMockData] - public void Return_configs_that_exist_in_guide( - [Frozen] ICustomFormatGuideService guide, - CustomFormatConfigPhase sut) + [Test] + public void Return_configs_that_exist_in_guide() { + var fixture = NSubstituteFixture.Create(); + + var guide = fixture.Freeze(); guide.GetCustomFormatData(default!).ReturnsForAnyArgs(new[] { NewCf.Data("one", "cf1"), NewCf.Data("two", "cf2") }); - var config = NewConfig.Radarr() with + fixture.Inject(NewConfig.Radarr() with { CustomFormats = new List { @@ -33,11 +35,11 @@ public class CustomFormatConfigPhaseTest } } } - }; + }); var context = new CustomFormatPipelineContext(); - - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -46,17 +48,18 @@ public class CustomFormatConfigPhaseTest }); } - [Test, AutoMockData] - public void Skip_configs_that_do_not_exist_in_guide( - [Frozen] ICustomFormatGuideService guide, - CustomFormatConfigPhase sut) + [Test] + public void Skip_configs_that_do_not_exist_in_guide() { + var fixture = NSubstituteFixture.Create(); + + var guide = fixture.Freeze(); guide.GetCustomFormatData(default!).ReturnsForAnyArgs(new[] { NewCf.Data("", "cf4") }); - var config = NewConfig.Radarr() with + fixture.Inject(NewConfig.Radarr() with { CustomFormats = new List { @@ -70,11 +73,11 @@ public class CustomFormatConfigPhaseTest } } } - }; + }); var context = new CustomFormatPipelineContext(); - - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEmpty(); } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/RadarrMediaNamingConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/RadarrMediaNamingConfigPhaseTest.cs index 8e8a0fbc..648d6035 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/RadarrMediaNamingConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/RadarrMediaNamingConfigPhaseTest.cs @@ -1,3 +1,4 @@ +using AutoFixture; using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; @@ -25,14 +26,15 @@ public class RadarrMediaNamingConfigPhaseTest } }; - [Test, AutoMockData] - public async Task Radarr_naming( - [Frozen] IMediaNamingGuideService guide, - RadarrMediaNamingConfigPhase sut) + [Test] + public async Task Radarr_naming() { + var fixture = NSubstituteFixture.Create(); + + var guide = fixture.Freeze(); guide.GetRadarrNamingData().Returns(RadarrNamingData); - var config = new RadarrConfiguration + fixture.Inject(new RadarrConfiguration { InstanceName = "radarr", MediaNaming = new RadarrMediaNamingConfig @@ -44,9 +46,10 @@ public class RadarrMediaNamingConfigPhaseTest Standard = "emby" } } - }; + }); - var result = await sut.ProcessNaming(config, guide, new NamingFormatLookup()); + var sut = fixture.Create(); + var result = await sut.ProcessNaming(guide, new NamingFormatLookup()); result.Should().NotBeNull(); result.Should().BeEquivalentTo(new RadarrMediaNamingDto diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/SonarrMediaNamingConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/SonarrMediaNamingConfigPhaseTest.cs index 46ae12e7..46bc24df 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/SonarrMediaNamingConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/Config/SonarrMediaNamingConfigPhaseTest.cs @@ -1,3 +1,4 @@ +using AutoFixture; using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases.Config; using Recyclarr.Compatibility.Sonarr; @@ -45,15 +46,16 @@ public class SonarrMediaNamingConfigPhaseTest } }; - [Test, AutoMockData] - public async Task Sonarr_v4_naming( - [Frozen] ISonarrCapabilityFetcher capabilities, - [Frozen] IMediaNamingGuideService guide, - SonarrMediaNamingConfigPhase sut) + [Test] + public async Task Sonarr_v4_naming() { + var fixture = NSubstituteFixture.Create(); + + fixture.Freeze(); // Frozen for instance sharing + var guide = fixture.Freeze(); guide.GetSonarrNamingData().Returns(SonarrNamingData); - var config = new SonarrConfiguration + fixture.Inject(new SonarrConfiguration { InstanceName = "sonarr", MediaNaming = new SonarrMediaNamingConfig @@ -68,9 +70,10 @@ public class SonarrMediaNamingConfigPhaseTest Anime = "default" } } - }; + }); - var result = await sut.ProcessNaming(config, guide, new NamingFormatLookup()); + var sut = fixture.Create(); + var result = await sut.ProcessNaming(guide, new NamingFormatLookup()); result.Should().NotBeNull(); result.Should().BeEquivalentTo(new SonarrMediaNamingDto @@ -84,15 +87,16 @@ public class SonarrMediaNamingConfigPhaseTest }); } - [Test, AutoMockData] - public async Task Sonarr_invalid_names( - [Frozen] ISonarrCapabilityFetcher capabilities, - [Frozen] IMediaNamingGuideService guide, - SonarrMediaNamingConfigPhase sut) + [Test] + public async Task Sonarr_invalid_names() { + var fixture = NSubstituteFixture.Create(); + + fixture.Freeze(); // Frozen for instance sharing + var guide = fixture.Freeze(); guide.GetSonarrNamingData().Returns(SonarrNamingData); - var config = new SonarrConfiguration + fixture.Inject(new SonarrConfiguration { InstanceName = "sonarr", MediaNaming = new SonarrMediaNamingConfig @@ -107,10 +111,11 @@ public class SonarrMediaNamingConfigPhaseTest Anime = "bad5" } } - }; + }); + var sut = fixture.Create(); var lookup = new NamingFormatLookup(); - var result = await sut.ProcessNaming(config, guide, lookup); + var result = await sut.ProcessNaming(guide, lookup); result.Should().NotBeNull(); result.Should().BeEquivalentTo(new SonarrMediaNamingDto diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseRadarrTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseRadarrTest.cs index f4791b0d..c11ab601 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseRadarrTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseRadarrTest.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Recyclarr.Cli.Pipelines.MediaNaming; using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; namespace Recyclarr.Cli.Tests.Pipelines.MediaNaming; @@ -29,7 +28,7 @@ public class MediaNamingTransactionPhaseRadarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ConfigOutput.Dto, o => o.RespectingRuntimeTypes()); } @@ -52,7 +51,7 @@ public class MediaNamingTransactionPhaseRadarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ApiFetchOutput, o => o.RespectingRuntimeTypes()); } @@ -80,7 +79,7 @@ public class MediaNamingTransactionPhaseRadarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ConfigOutput.Dto, o => o.RespectingRuntimeTypes()); } @@ -108,7 +107,7 @@ public class MediaNamingTransactionPhaseRadarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new RadarrMediaNamingDto { diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseSonarrTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseSonarrTest.cs index 0cce942a..e4cc5937 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseSonarrTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/MediaNaming/MediaNamingTransactionPhaseSonarrTest.cs @@ -1,7 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Recyclarr.Cli.Pipelines.MediaNaming; using Recyclarr.Cli.Pipelines.MediaNaming.PipelinePhases; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.MediaNaming; namespace Recyclarr.Cli.Tests.Pipelines.MediaNaming; @@ -31,7 +30,7 @@ public class MediaNamingTransactionPhaseSonarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ConfigOutput.Dto, o => o.RespectingRuntimeTypes()); } @@ -57,7 +56,7 @@ public class MediaNamingTransactionPhaseSonarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ApiFetchOutput, o => o.RespectingRuntimeTypes()); } @@ -91,7 +90,7 @@ public class MediaNamingTransactionPhaseSonarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(context.ConfigOutput.Dto, o => o.RespectingRuntimeTypes()); } @@ -125,7 +124,7 @@ public class MediaNamingTransactionPhaseSonarrTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new SonarrMediaNamingDto { diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs index 089b999e..f1b6d1a1 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileConfigPhaseTest.cs @@ -1,3 +1,4 @@ +using AutoFixture; using Recyclarr.Cli.Pipelines.CustomFormat.Models; using Recyclarr.Cli.Pipelines.QualityProfile; using Recyclarr.Cli.Pipelines.QualityProfile.PipelinePhases; @@ -17,18 +18,19 @@ public class QualityProfileConfigPhaseTest }; } - [Test, AutoMockData] - public void All_cfs_use_score_override( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void All_cfs_use_score_override() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.DataWithScore("", "id1", 101, 1), NewCf.DataWithScore("", "id2", 201, 2) }); - var config = SetupCfs(new CustomFormatConfig + fixture.Inject(SetupCfs(new CustomFormatConfig { TrashIds = new[] {"id1", "id2"}, QualityProfiles = new List @@ -39,10 +41,12 @@ public class QualityProfileConfigPhaseTest Score = 100 } } - }); + })); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -51,18 +55,19 @@ public class QualityProfileConfigPhaseTest o => o.Excluding(x => x.ShouldCreate)); } - [Test, AutoMockData] - public void All_cfs_use_guide_scores_with_no_override( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void All_cfs_use_guide_scores_with_no_override() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.DataWithScore("", "id1", 100, 1), NewCf.DataWithScore("", "id2", 200, 2) }); - var config = SetupCfs(new CustomFormatConfig + fixture.Inject(SetupCfs(new CustomFormatConfig { TrashIds = new[] {"id1", "id2"}, QualityProfiles = new List @@ -72,10 +77,11 @@ public class QualityProfileConfigPhaseTest Name = "test_profile" } } - }); + })); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -84,18 +90,19 @@ public class QualityProfileConfigPhaseTest o => o.Excluding(x => x.ShouldCreate)); } - [Test, AutoMockData] - public void No_cfs_returned_when_no_score_in_guide_or_config( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void No_cfs_returned_when_no_score_in_guide_or_config() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.Data("", "id1", 1), NewCf.Data("", "id2", 2) }); - var config = SetupCfs(new CustomFormatConfig + fixture.Inject(SetupCfs(new CustomFormatConfig { TrashIds = new[] {"id1", "id2"}, QualityProfiles = new List @@ -105,10 +112,11 @@ public class QualityProfileConfigPhaseTest Name = "test_profile" } } - }); + })); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -117,17 +125,18 @@ public class QualityProfileConfigPhaseTest o => o.Excluding(x => x.ShouldCreate).Excluding(x => x.ScorelessCfs)); } - [Test, AutoMockData] - public void Skip_duplicate_cfs_with_same_and_different_scores( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void Skip_duplicate_cfs_with_same_and_different_scores() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.DataWithScore("", "id1", 100, 1) }); - var config = SetupCfs( + fixture.Inject(SetupCfs( new CustomFormatConfig { TrashIds = new[] {"id1"} @@ -164,10 +173,11 @@ public class QualityProfileConfigPhaseTest new() {Name = "test_profile2", Score = 100} } } - ); + )); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -177,11 +187,12 @@ public class QualityProfileConfigPhaseTest o => o.Excluding(x => x.ShouldCreate)); } - [Test, AutoMockData] - public void All_cfs_use_score_set( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void All_cfs_use_score_set() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.DataWithScores("", "id1", 1, ("default", 101), ("set1", 102)), @@ -210,9 +221,11 @@ public class QualityProfileConfigPhaseTest } } }; + fixture.Inject(config); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEquivalentTo(new[] { @@ -224,12 +237,12 @@ public class QualityProfileConfigPhaseTest o => o.Excluding(x => x.ShouldCreate)); } - [Test, AutoMockData] - public void Empty_trash_ids_list_is_ignored( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void Empty_trash_ids_list_is_ignored() { - var config = SetupCfs(new CustomFormatConfig + var fixture = NSubstituteFixture.Create(); + + fixture.Inject(SetupCfs(new CustomFormatConfig { TrashIds = Array.Empty(), QualityProfiles = new List @@ -240,33 +253,36 @@ public class QualityProfileConfigPhaseTest Score = 100 } } - }); + })); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEmpty(); } - [Test, AutoMockData] - public void Empty_quality_profiles_is_ignored( - [Frozen] ProcessedCustomFormatCache cache, - QualityProfileConfigPhase sut) + [Test] + public void Empty_quality_profiles_is_ignored() { + var fixture = NSubstituteFixture.Create(); + + var cache = fixture.Freeze(); cache.AddCustomFormats(new[] { NewCf.DataWithScore("", "id1", 101, 1), NewCf.DataWithScore("", "id2", 201, 2) }); - var config = SetupCfs(new CustomFormatConfig + fixture.Inject(SetupCfs(new CustomFormatConfig { TrashIds = new[] {"id1", "id2"}, QualityProfiles = Array.Empty() - }); + })); var context = new QualityProfilePipelineContext(); - sut.Execute(context, config); + var sut = fixture.Create(); + sut.Execute(context); context.ConfigOutput.Should().BeEmpty(); } diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhaseTest.cs index 09e46021..ee094ba2 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualityProfile/PipelinePhases/QualityProfileTransactionPhaseTest.cs @@ -31,7 +31,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new QualityProfileTransactionData { @@ -88,7 +88,7 @@ public class QualityProfileTransactionPhaseTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new QualityProfileTransactionData { @@ -159,7 +159,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.ChangedProfiles.Should() .ContainSingle().Which.Profile.UpdatedScores.Should() @@ -203,7 +203,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new QualityProfileTransactionData()); } @@ -246,7 +246,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.UnchangedProfiles.Should() .ContainSingle().Which.Profile.UpdatedScores.Should() @@ -293,7 +293,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.ChangedProfiles.Should() .ContainSingle().Which.Profile.UpdatedScores.Should() @@ -352,7 +352,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.ChangedProfiles.Should() .ContainSingle().Which.Profile.UpdatedScores.Should() @@ -409,7 +409,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.ChangedProfiles.Should() .ContainSingle().Which.Profile.UpdatedScores.Should() @@ -465,7 +465,7 @@ public class QualityProfileTransactionPhaseTest ApiFetchOutput = new QualityProfileServiceData(dtos, new QualityProfileDto()) }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.ChangedProfiles.Should() .ContainSingle().Which.Profile.InvalidExceptCfNames.Should() diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs index afbdfd80..afd28508 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeConfigPhaseTest.cs @@ -10,13 +10,14 @@ namespace Recyclarr.Cli.Tests.Pipelines.QualitySize.PipelinePhases; public class QualitySizeConfigPhaseTest { [Test, AutoMockData] - public void Do_nothing_if_no_quality_definition(QualitySizeConfigPhase sut) + public void Do_nothing_if_no_quality_definition( + [Frozen] IServiceConfiguration config, + QualitySizeConfigPhase sut) { var context = new QualitySizePipelineContext(); - var config = Substitute.For(); config.QualityDefinition.ReturnsNull(); - sut.Execute(context, config); + sut.Execute(context); context.ConfigOutput.Should().BeNull(); } @@ -24,9 +25,9 @@ public class QualitySizeConfigPhaseTest [Test, AutoMockData] public void Do_nothing_if_no_matching_quality_definition( [Frozen] IQualitySizeGuideService guide, + [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) { - var config = Substitute.For(); config.QualityDefinition.Returns(new QualityDefinitionConfig {Type = "not_real"}); guide.GetQualitySizeData(default!).ReturnsForAnyArgs(new[] @@ -36,7 +37,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context, config); + sut.Execute(context); context.ConfigOutput.Should().BeNull(); } @@ -48,9 +49,9 @@ public class QualitySizeConfigPhaseTest string testPreferred, string expectedPreferred, [Frozen] IQualitySizeGuideService guide, + [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) { - var config = Substitute.For(); config.QualityDefinition.Returns(new QualityDefinitionConfig { Type = "real", @@ -64,7 +65,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context, config); + sut.Execute(context); config.QualityDefinition.Should().NotBeNull(); config.QualityDefinition!.PreferredRatio.Should().Be(decimal.Parse(expectedPreferred)); @@ -73,9 +74,9 @@ public class QualitySizeConfigPhaseTest [Test, AutoMockData] public void Preferred_is_set_via_ratio( [Frozen] IQualitySizeGuideService guide, + [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) { - var config = Substitute.For(); config.QualityDefinition.Returns(new QualityDefinitionConfig { Type = "real", @@ -96,7 +97,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context, config); + sut.Execute(context); context.ConfigOutput.Should().NotBeNull(); context.ConfigOutput!.Qualities.Should().BeEquivalentTo(new[] @@ -113,9 +114,9 @@ public class QualitySizeConfigPhaseTest [Test, AutoMockData] public void Preferred_is_set_via_guide( [Frozen] IQualitySizeGuideService guide, + [Frozen] IServiceConfiguration config, QualitySizeConfigPhase sut) { - var config = Substitute.For(); config.QualityDefinition.Returns(new QualityDefinitionConfig { Type = "real" @@ -135,7 +136,7 @@ public class QualitySizeConfigPhaseTest var context = new QualitySizePipelineContext(); - sut.Execute(context, config); + sut.Execute(context); context.ConfigOutput.Should().NotBeNull(); context.ConfigOutput!.Qualities.Should().BeEquivalentTo(new[] diff --git a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhaseTest.cs b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhaseTest.cs index 3144ce09..0defbcc3 100644 --- a/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhaseTest.cs +++ b/tests/Recyclarr.Cli.Tests/Pipelines/QualitySize/PipelinePhases/QualitySizeTransactionPhaseTest.cs @@ -1,6 +1,5 @@ using Recyclarr.Cli.Pipelines.QualitySize; using Recyclarr.Cli.Pipelines.QualitySize.PipelinePhases; -using Recyclarr.Config.Models; using Recyclarr.ServarrApi.QualityDefinition; using Recyclarr.TrashGuide.QualitySize; @@ -32,7 +31,7 @@ public class QualitySizeTransactionPhaseTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEmpty(); } @@ -70,7 +69,7 @@ public class QualitySizeTransactionPhaseTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEmpty(); } @@ -108,7 +107,7 @@ public class QualitySizeTransactionPhaseTest } }; - sut.Execute(context, Substitute.For()); + sut.Execute(context); context.TransactionOutput.Should().BeEquivalentTo(new List { diff --git a/tests/Recyclarr.IntegrationTests/CustomFormatServiceTest.cs b/tests/Recyclarr.IntegrationTests/CustomFormatServiceTest.cs index a91aae25..22dbc95d 100644 --- a/tests/Recyclarr.IntegrationTests/CustomFormatServiceTest.cs +++ b/tests/Recyclarr.IntegrationTests/CustomFormatServiceTest.cs @@ -1,7 +1,9 @@ using Flurl.Http.Testing; using Recyclarr.Common; +using Recyclarr.Config; using Recyclarr.Config.Models; using Recyclarr.ServarrApi.CustomFormat; +using Recyclarr.Tests.TestLibrary; namespace Recyclarr.IntegrationTests; @@ -13,13 +15,18 @@ public class CustomFormatServiceTest : IntegrationTestFixture { var resourceData = new ResourceDataReader(typeof(CustomFormatServiceTest), "Data"); var jsonBody = resourceData.ReadData("issue_178.json"); - var config = new RadarrConfiguration {InstanceName = "instance"}; using var http = new HttpTest(); http.RespondWith(jsonBody); - var sut = Resolve(); - var result = await sut.GetCustomFormats(config); + var scopeFactory = Resolve(); + using var scope = scopeFactory.Start(new RadarrConfiguration + { + InstanceName = "instance" + }); + + var sut = scope.Resolve(); + var result = await sut.GetCustomFormats(); result.Should().HaveCountGreaterThan(5); } diff --git a/tests/Recyclarr.IntegrationTests/IntegrationTestFixture.cs b/tests/Recyclarr.IntegrationTests/IntegrationTestFixture.cs index 4c769d1c..6b66cdc4 100644 --- a/tests/Recyclarr.IntegrationTests/IntegrationTestFixture.cs +++ b/tests/Recyclarr.IntegrationTests/IntegrationTestFixture.cs @@ -91,7 +91,7 @@ public abstract class IntegrationTestFixture : IDisposable builder.RegisterMockFor(m => { // By default, choose some extremely high number so that all the newest features are enabled. - m.GetVersion(default!).ReturnsForAnyArgs(_ => new Version("99.0.0.0")); + m.GetVersion().ReturnsForAnyArgs(_ => new Version("99.0.0.0")); }); } diff --git a/tests/Recyclarr.Tests.TestLibrary/TestConfigurationScope.cs b/tests/Recyclarr.Tests.TestLibrary/TestConfigurationScope.cs new file mode 100644 index 00000000..af7c6d9a --- /dev/null +++ b/tests/Recyclarr.Tests.TestLibrary/TestConfigurationScope.cs @@ -0,0 +1,12 @@ +using Autofac; +using Recyclarr.Config; + +namespace Recyclarr.Tests.TestLibrary; + +public class TestConfigurationScope(ILifetimeScope scope) : ConfigurationScope(scope) +{ + public T Resolve() where T : notnull + { + return scope.Resolve(); + } +} diff --git a/tests/Recyclarr.Tests/Compatibility/Sonarr/SonarrCapabilityEnforcerTest.cs b/tests/Recyclarr.Tests/Compatibility/Sonarr/SonarrCapabilityEnforcerTest.cs index e6857e1a..83003017 100644 --- a/tests/Recyclarr.Tests/Compatibility/Sonarr/SonarrCapabilityEnforcerTest.cs +++ b/tests/Recyclarr.Tests/Compatibility/Sonarr/SonarrCapabilityEnforcerTest.cs @@ -1,6 +1,5 @@ using Recyclarr.Compatibility; using Recyclarr.Compatibility.Sonarr; -using Recyclarr.Tests.TestLibrary; namespace Recyclarr.Tests.Compatibility.Sonarr; @@ -12,13 +11,12 @@ public class SonarrCapabilityEnforcerTest [Frozen] ISonarrCapabilityFetcher fetcher, SonarrCapabilityEnforcer sut) { - var config = NewConfig.Sonarr(); var min = SonarrCapabilities.MinimumVersion; - fetcher.GetCapabilities(default!).ReturnsForAnyArgs( + fetcher.GetCapabilities().ReturnsForAnyArgs( new SonarrCapabilities(new Version(min.Major - 1, min.Minor, min.Build, min.Revision))); - var act = () => sut.Check(config); + var act = sut.Check; act.Should().ThrowAsync().WithMessage("*minimum*"); }