diff --git a/src/Refitter.Core/ApizrOptionsBuilder.cs b/src/Refitter.Core/ApizrOptionsBuilder.cs new file mode 100644 index 000000000..d9e7f3370 --- /dev/null +++ b/src/Refitter.Core/ApizrOptionsBuilder.cs @@ -0,0 +1,73 @@ +using System.Text; +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class ApizrOptionsBuilder : IApizrOptionsBuilder +{ + private readonly StringBuilder _optionsCode; + private readonly StringBuilder _usingsCode; + private readonly HashSet _packages = new(); + private bool _hasOptions; + + public ApizrOptionsBuilder(string initialOptionsCode, string initialUsings) + { + _optionsCode = new StringBuilder(initialOptionsCode); + _usingsCode = new StringBuilder(initialUsings); + _usingsCode.AppendLine(); + } + + public bool HasOptions => _hasOptions; + + public void WithBaseAddress(string baseUrl, string duplicateStrategy) + { + _optionsCode.AppendLine(); + _optionsCode.Append($" .WithBaseAddress(\"{baseUrl}\", {duplicateStrategy})"); + _hasOptions = true; + } + + public void WithDelegatingHandler(string handlerType) + { + _optionsCode.AppendLine(); + _optionsCode.Append($" .WithDelegatingHandler<{handlerType}>()"); + _hasOptions = true; + } + + public void ConfigureHttpClientBuilder(Action configure) + { + _optionsCode.AppendLine(); + configure(_optionsCode); + _hasOptions = true; + } + + public void AppendOptionsCode(string code) + { + _optionsCode.Append(code); + _hasOptions = true; + } + + public void AddPackage(ApizrPackages package) + { + _packages.Add(package); + } + + public void AddUsing(string usingDirective) + { + _usingsCode.Append(" "); + _usingsCode.AppendLine(usingDirective); + } + + public string BuildOptionsCode() + { + if (_hasOptions) + _optionsCode.Append(";"); + else + _optionsCode.Clear(); + + return _optionsCode.ToString(); + } + + public string GetUsings() => _usingsCode.ToString(); + + public List GetPackages() => _packages.ToList(); +} diff --git a/src/Refitter.Core/ApizrRegistrationGenerator.cs b/src/Refitter.Core/ApizrRegistrationGenerator.cs index 6b836c321..5d4199b2d 100644 --- a/src/Refitter.Core/ApizrRegistrationGenerator.cs +++ b/src/Refitter.Core/ApizrRegistrationGenerator.cs @@ -1,4 +1,3 @@ -using System.Globalization; using System.Text; using Refitter.Core.Settings; @@ -6,6 +5,17 @@ namespace Refitter.Core; internal static class ApizrRegistrationGenerator { + private static readonly IApizrOptionsAdapter[] Adapters = + [ + new HttpMessageHandlerAdapter(), + new RetryHandlerAdapter(), + new CacheProviderAdapter(), + new MappingProviderAdapter(), + new PriorityAdapter(), + new MediationAdapter(), + new FileTransferAdapter(), + ]; + public static string Generate( RefitGeneratorSettings settings, string[] interfaceNames, @@ -40,21 +50,11 @@ public static string Generate( methodName = hasManyApis ? $"Build{formatedTitle}ApizrManagers" : $"Build{formatedTitle}ApizrManager"; } - var optionsCode = + var initialOptionsCode = $$""" optionsBuilder ??= _ => { }; // Default empty options if null optionsBuilder += options => options """; - var optionsCodeBuilder = new StringBuilder(optionsCode); - - if (hasBaseUrl) - { - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithBaseAddress("{{iocSettings!.BaseUrl}}", ApizrDuplicateStrategy.Ignore) - """); - } var usings = iocSettings?.TransientErrorHandler switch { @@ -83,206 +83,27 @@ public static string Generate( """ }; - var apizrPackages = new List(); - var usingsCodeBuilder = new StringBuilder(usings); - usingsCodeBuilder.AppendLine(); - - if (iocSettings?.HttpMessageHandlers.Length > 0) - { - foreach (string httpMessageHandler in iocSettings.HttpMessageHandlers) - { - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithDelegatingHandler<{{httpMessageHandler}}>() - """); - } - } - - if (iocSettings?.TransientErrorHandler == TransientErrorHandler.Polly) - { - var durationString = iocSettings.FirstBackoffRetryInSeconds.ToString(CultureInfo.InvariantCulture); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .ConfigureHttpClientBuilder(builder => builder - .AddPolicyHandler( - HttpPolicyExtensions - .HandleTransientHttpError() - .WaitAndRetryAsync( - Backoff.DecorrelatedJitterBackoffV2( - TimeSpan.FromSeconds({{durationString}}), - {{iocSettings.MaxRetryCount}})))) - """); - } - else if (iocSettings?.TransientErrorHandler == TransientErrorHandler.HttpResilience) - { - var durationString = iocSettings.FirstBackoffRetryInSeconds.ToString(CultureInfo.InvariantCulture); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .ConfigureHttpClientBuilder(builder => builder - .AddStandardResilienceHandler(config => - { - config.Retry = new HttpRetryStrategyOptions - { - UseJitter = true, - MaxRetryAttempts = {{iocSettings.MaxRetryCount}}, - Delay = TimeSpan.FromSeconds({{durationString}}) - }; - })) - """); - } - - switch (settings.ApizrSettings.WithCacheProvider) - { - case CacheProviderType.Akavache: - apizrPackages.Add(ApizrPackages.Apizr_Integrations_Akavache); - usingsCodeBuilder.AppendLine( - $$""" - using Akavache; - """); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithAkavacheCacheHandler() - """); - break; - case CacheProviderType.MonkeyCache: - apizrPackages.Add(ApizrPackages.Apizr_Integrations_MonkeyCache); - usingsCodeBuilder.AppendLine( - $$""" - using MonkeyCache; - """); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithCacheHandler(new MonkeyCacheHandler(Barrel.Current)) - """); - break; - case CacheProviderType.InMemory when isDependencyInjectionExtension: - apizrPackages.Add(ApizrPackages.Apizr_Extensions_Microsoft_Caching); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithInMemoryCacheHandler() - """); - break; - case CacheProviderType.DistributedAsString when isDependencyInjectionExtension: - apizrPackages.Add(ApizrPackages.Apizr_Extensions_Microsoft_Caching); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithDistributedCacheHandler() - """); - break; - case CacheProviderType.DistributedAsByteArray when isDependencyInjectionExtension: - apizrPackages.Add(ApizrPackages.Apizr_Extensions_Microsoft_Caching); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithDistributedCacheHandler() - """); - break; - } - - switch (settings.ApizrSettings.WithMappingProvider) - { - case MappingProviderType.AutoMapper: - apizrPackages.Add(ApizrPackages.Apizr_Integrations_AutoMapper); - usingsCodeBuilder.AppendLine( - $$""" - using AutoMapper; - """); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append(isDependencyInjectionExtension ? - $$""" - .WithAutoMapperMappingHandler() - """ : - $$""" - .WithAutoMapperMappingHandler(new MapperConfiguration(config => { /* YOUR_MAPPINGS_HERE */ })) - """); - break; - case MappingProviderType.Mapster: - apizrPackages.Add(ApizrPackages.Apizr_Integrations_Mapster); - usingsCodeBuilder.AppendLine( - $$""" - using Mapster; - """); - if (isDependencyInjectionExtension) - usingsCodeBuilder.AppendLine( - $$""" - using MapsterMapper; - """); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append(isDependencyInjectionExtension ? - $$""" - .WithMapsterMappingHandler() - """ : - $$""" - .WithMapsterMappingHandler(new Mapper()) - """); - break; - } - - if (settings.ApizrSettings.WithPriority) - { - apizrPackages.Add(ApizrPackages.Apizr_Integrations_Fusillade); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithPriority() - """); - } + var builder = new ApizrOptionsBuilder(initialOptionsCode, usings); - if (settings.ApizrSettings.WithMediation && isDependencyInjectionExtension) + if (hasBaseUrl) { - apizrPackages.Add(ApizrPackages.Apizr_Integrations_MediatR); - usingsCodeBuilder.AppendLine( - $$""" - using MediatR; - """); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithMediation() - """); + builder.WithBaseAddress(iocSettings!.BaseUrl!, "ApizrDuplicateStrategy.Ignore"); } - if (settings.ApizrSettings.WithFileTransfer) + foreach (var adapter in Adapters) { - if (isDependencyInjectionExtension) - { - if (settings.ApizrSettings.WithMediation) - { - apizrPackages.Add(ApizrPackages.Apizr_Integrations_FileTransfer_MediatR); - optionsCodeBuilder.AppendLine(); - optionsCodeBuilder.Append( - $$""" - .WithFileTransferMediation() - """); - } - else - { - apizrPackages.Add(ApizrPackages.Apizr_Extensions_Microsoft_FileTransfer); - } - } - else + if (adapter.CanApply(settings)) { - apizrPackages.Add(ApizrPackages.Apizr_Integrations_FileTransfer); + adapter.Apply(builder, settings); } } - apizrPackages.Add(ApizrPackages.Apizr); - usingsCodeBuilder.AppendLine( - $$""" - using Apizr; - """); + builder.AddPackage(ApizrPackages.Apizr); + builder.AddUsing("using Apizr;"); - if (optionsCodeBuilder.ToString().Contains(".With")) - optionsCodeBuilder.Append(";"); - else - optionsCodeBuilder.Clear(); + var optionsCode = builder.BuildOptionsCode(); + var usingsCodeBuilder = new StringBuilder(builder.GetUsings()); + var apizrPackages = builder.GetPackages(); var packageCodeBuilder = new StringBuilder(); var packages = apizrPackages.OrderByDescending(p => p).ToList(); @@ -313,6 +134,7 @@ public static string Generate( // Please make sure to complete the following steps resulting from your configuration: """); } + for (int i = 0; i < packages.Count; i++) { if (i == 0 || !packages[i - 1].HasFlag(packages[i])) @@ -345,9 +167,7 @@ public static string Generate( if (hasBaseUrl) { usingsCodeBuilder.AppendLine( - $$""" - using Apizr.Configuring; - """); + " using Apizr.Configuring;"); } #region Registry @@ -355,9 +175,7 @@ public static string Generate( if (hasManyApis) { usingsCodeBuilder.AppendLine( - $$""" - using Apizr.Extending.Configuring.Common; - """); + "using Apizr.Extending.Configuring.Common;"); code.AppendLine( $$""" @@ -407,7 +225,7 @@ public static partial class IServiceCollectionExtensions code.AppendLine( $$""" - {{optionsCodeBuilder}} + {{optionsCode}} return services.AddApizr( registry => registry @@ -441,9 +259,7 @@ public static partial class IServiceCollectionExtensions else { usingsCodeBuilder.AppendLine( - $$""" - using Apizr.Extending.Configuring.Manager; - """); + " using Apizr.Extending.Configuring.Manager;"); code.AppendLine( $$""" @@ -493,7 +309,7 @@ public static partial class IServiceCollectionExtensions code.AppendLine( $$""" - {{optionsCodeBuilder}} + {{optionsCode}} return services.AddApizrManagerFor<{{interfaceNames[0]}}>(optionsBuilder); """); @@ -517,9 +333,7 @@ public static partial class IServiceCollectionExtensions if (hasManyApis) { usingsCodeBuilder.AppendLine( - $$""" - using Apizr.Configuring.Registry; - """); + " using Apizr.Configuring.Registry;"); code.AppendLine( $$""" @@ -550,7 +364,7 @@ public static partial class ApizrRegistration $$""" public static IApizrRegistry {{methodName}}(Action optionsBuilder) { - {{optionsCodeBuilder}} + {{optionsCode}} return ApizrBuilder.Current.CreateRegistry( registry => registry @@ -583,9 +397,7 @@ public static partial class ApizrRegistration else { usingsCodeBuilder.AppendLine( - $$""" - using Apizr.Configuring.Manager; - """); + " using Apizr.Configuring.Manager;"); code.AppendLine( $$""" @@ -616,7 +428,7 @@ public static partial class ApizrRegistration $$""" public static IApizrManager<{{interfaceNames[0]}}> {{methodName}}(Action optionsBuilder) { - {{optionsCodeBuilder}} + {{optionsCode}} return ApizrBuilder.Current.CreateManagerFor<{{interfaceNames[0]}}>(optionsBuilder); """); diff --git a/src/Refitter.Core/CacheProviderAdapter.cs b/src/Refitter.Core/CacheProviderAdapter.cs new file mode 100644 index 000000000..02a6f4941 --- /dev/null +++ b/src/Refitter.Core/CacheProviderAdapter.cs @@ -0,0 +1,46 @@ +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class CacheProviderAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.ApizrSettings!.WithCacheProvider != CacheProviderType.None; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + var isDependencyInjectionExtension = settings.DependencyInjectionSettings != null; + + switch (settings.ApizrSettings!.WithCacheProvider) + { + case CacheProviderType.Akavache: + builder.AddPackage(ApizrPackages.Apizr_Integrations_Akavache); + builder.AddUsing("using Akavache;"); + builder.AppendOptionsCode("\n .WithAkavacheCacheHandler()"); + break; + + case CacheProviderType.MonkeyCache: + builder.AddPackage(ApizrPackages.Apizr_Integrations_MonkeyCache); + builder.AddUsing("using MonkeyCache;"); + builder.AppendOptionsCode("\n .WithCacheHandler(new MonkeyCacheHandler(Barrel.Current))"); + break; + + case CacheProviderType.InMemory when isDependencyInjectionExtension: + builder.AddPackage(ApizrPackages.Apizr_Extensions_Microsoft_Caching); + builder.AppendOptionsCode("\n .WithInMemoryCacheHandler()"); + break; + + case CacheProviderType.DistributedAsString when isDependencyInjectionExtension: + builder.AddPackage(ApizrPackages.Apizr_Extensions_Microsoft_Caching); + builder.AppendOptionsCode("\n .WithDistributedCacheHandler()"); + break; + + case CacheProviderType.DistributedAsByteArray when isDependencyInjectionExtension: + builder.AddPackage(ApizrPackages.Apizr_Extensions_Microsoft_Caching); + builder.AppendOptionsCode("\n .WithDistributedCacheHandler()"); + break; + } + } +} diff --git a/src/Refitter.Core/FileTransferAdapter.cs b/src/Refitter.Core/FileTransferAdapter.cs new file mode 100644 index 000000000..5f4bc62bd --- /dev/null +++ b/src/Refitter.Core/FileTransferAdapter.cs @@ -0,0 +1,33 @@ +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class FileTransferAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.ApizrSettings!.WithFileTransfer; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + var isDependencyInjectionExtension = settings.DependencyInjectionSettings != null; + + if (isDependencyInjectionExtension) + { + if (settings.ApizrSettings!.WithMediation) + { + builder.AddPackage(ApizrPackages.Apizr_Integrations_FileTransfer_MediatR); + builder.AppendOptionsCode("\n .WithFileTransferMediation()"); + } + else + { + builder.AddPackage(ApizrPackages.Apizr_Extensions_Microsoft_FileTransfer); + } + } + else + { + builder.AddPackage(ApizrPackages.Apizr_Integrations_FileTransfer); + } + } +} diff --git a/src/Refitter.Core/HttpMessageHandlerAdapter.cs b/src/Refitter.Core/HttpMessageHandlerAdapter.cs new file mode 100644 index 000000000..d92ecda93 --- /dev/null +++ b/src/Refitter.Core/HttpMessageHandlerAdapter.cs @@ -0,0 +1,17 @@ +namespace Refitter.Core; + +internal class HttpMessageHandlerAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.DependencyInjectionSettings?.HttpMessageHandlers.Length > 0; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + foreach (string handler in settings.DependencyInjectionSettings!.HttpMessageHandlers) + { + builder.WithDelegatingHandler(handler); + } + } +} diff --git a/src/Refitter.Core/IApizrOptionsAdapter.cs b/src/Refitter.Core/IApizrOptionsAdapter.cs new file mode 100644 index 000000000..022e5e75d --- /dev/null +++ b/src/Refitter.Core/IApizrOptionsAdapter.cs @@ -0,0 +1,7 @@ +namespace Refitter.Core; + +internal interface IApizrOptionsAdapter +{ + bool CanApply(RefitGeneratorSettings settings); + void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings); +} diff --git a/src/Refitter.Core/IApizrOptionsBuilder.cs b/src/Refitter.Core/IApizrOptionsBuilder.cs new file mode 100644 index 000000000..df379a06d --- /dev/null +++ b/src/Refitter.Core/IApizrOptionsBuilder.cs @@ -0,0 +1,18 @@ +using System.Text; +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal interface IApizrOptionsBuilder +{ + void WithBaseAddress(string baseUrl, string duplicateStrategy); + void WithDelegatingHandler(string handlerType); + void ConfigureHttpClientBuilder(Action configure); + void AppendOptionsCode(string code); + void AddPackage(ApizrPackages package); + void AddUsing(string usingDirective); + bool HasOptions { get; } + string BuildOptionsCode(); + string GetUsings(); + List GetPackages(); +} diff --git a/src/Refitter.Core/MappingProviderAdapter.cs b/src/Refitter.Core/MappingProviderAdapter.cs new file mode 100644 index 000000000..4a43a53f4 --- /dev/null +++ b/src/Refitter.Core/MappingProviderAdapter.cs @@ -0,0 +1,42 @@ +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class MappingProviderAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.ApizrSettings!.WithMappingProvider != MappingProviderType.None; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + var isDependencyInjectionExtension = settings.DependencyInjectionSettings != null; + + switch (settings.ApizrSettings!.WithMappingProvider) + { + case MappingProviderType.AutoMapper: + builder.AddPackage(ApizrPackages.Apizr_Integrations_AutoMapper); + builder.AddUsing("using AutoMapper;"); + if (isDependencyInjectionExtension) + builder.AppendOptionsCode("\n .WithAutoMapperMappingHandler()"); + else + builder.AppendOptionsCode("\n .WithAutoMapperMappingHandler(new MapperConfiguration(config => { /* YOUR_MAPPINGS_HERE */ }))"); + break; + + case MappingProviderType.Mapster: + builder.AddPackage(ApizrPackages.Apizr_Integrations_Mapster); + builder.AddUsing("using Mapster;"); + if (isDependencyInjectionExtension) + { + builder.AddUsing("using MapsterMapper;"); + builder.AppendOptionsCode("\n .WithMapsterMappingHandler()"); + } + else + { + builder.AppendOptionsCode("\n .WithMapsterMappingHandler(new Mapper())"); + } + break; + } + } +} diff --git a/src/Refitter.Core/MediationAdapter.cs b/src/Refitter.Core/MediationAdapter.cs new file mode 100644 index 000000000..6d2e61105 --- /dev/null +++ b/src/Refitter.Core/MediationAdapter.cs @@ -0,0 +1,19 @@ +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class MediationAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.ApizrSettings!.WithMediation && + settings.DependencyInjectionSettings != null; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + builder.AddPackage(ApizrPackages.Apizr_Integrations_MediatR); + builder.AddUsing("using MediatR;"); + builder.AppendOptionsCode("\n .WithMediation()"); + } +} diff --git a/src/Refitter.Core/PriorityAdapter.cs b/src/Refitter.Core/PriorityAdapter.cs new file mode 100644 index 000000000..b0c51e5d6 --- /dev/null +++ b/src/Refitter.Core/PriorityAdapter.cs @@ -0,0 +1,17 @@ +using Refitter.Core.Settings; + +namespace Refitter.Core; + +internal class PriorityAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.ApizrSettings!.WithPriority; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + builder.AddPackage(ApizrPackages.Apizr_Integrations_Fusillade); + builder.AppendOptionsCode("\n .WithPriority()"); + } +} diff --git a/src/Refitter.Core/RetryHandlerAdapter.cs b/src/Refitter.Core/RetryHandlerAdapter.cs new file mode 100644 index 000000000..d10dcb152 --- /dev/null +++ b/src/Refitter.Core/RetryHandlerAdapter.cs @@ -0,0 +1,54 @@ +using System.Globalization; +using System.Text; + +namespace Refitter.Core; + +internal class RetryHandlerAdapter : IApizrOptionsAdapter +{ + public bool CanApply(RefitGeneratorSettings settings) + { + return settings.DependencyInjectionSettings?.TransientErrorHandler is + TransientErrorHandler.Polly or + TransientErrorHandler.HttpResilience; + } + + public void Apply(IApizrOptionsBuilder builder, RefitGeneratorSettings settings) + { + var iocSettings = settings.DependencyInjectionSettings!; + var durationString = iocSettings.FirstBackoffRetryInSeconds.ToString(CultureInfo.InvariantCulture); + + builder.ConfigureHttpClientBuilder(httpBuilder => + { + if (iocSettings.TransientErrorHandler == TransientErrorHandler.Polly) + { + builder.AddUsing("using Polly;"); + builder.AddUsing("using Polly.Contrib.WaitAndRetry;"); + builder.AddUsing("using Polly.Extensions.Http;"); + httpBuilder.Append( + $" .ConfigureHttpClientBuilder(builder => builder{Environment.NewLine}" + + $" .AddPolicyHandler({Environment.NewLine}" + + $" HttpPolicyExtensions{Environment.NewLine}" + + $" .HandleTransientHttpError(){Environment.NewLine}" + + $" .WaitAndRetryAsync({Environment.NewLine}" + + $" Backoff.DecorrelatedJitterBackoffV2({Environment.NewLine}" + + $" TimeSpan.FromSeconds({durationString}),{Environment.NewLine}" + + $" {iocSettings.MaxRetryCount}))))"); + } + else if (iocSettings.TransientErrorHandler == TransientErrorHandler.HttpResilience) + { + builder.AddUsing("using Microsoft.Extensions.Http.Resilience;"); + httpBuilder.Append( + $" .ConfigureHttpClientBuilder(builder => builder{Environment.NewLine}" + + $" .AddStandardResilienceHandler(config =>{Environment.NewLine}" + + $" {{{Environment.NewLine}" + + $" config.Retry = new HttpRetryStrategyOptions{Environment.NewLine}" + + $" {{{Environment.NewLine}" + + $" UseJitter = true,{Environment.NewLine}" + + $" MaxRetryAttempts = {iocSettings.MaxRetryCount},{Environment.NewLine}" + + $" Delay = TimeSpan.FromSeconds({durationString}){Environment.NewLine}" + + $" }};{Environment.NewLine}" + + $" }}))"); + } + }); + } +} diff --git a/src/Refitter.Tests/Apizr/ApizrOptionsAdapterPipelineTests.cs b/src/Refitter.Tests/Apizr/ApizrOptionsAdapterPipelineTests.cs new file mode 100644 index 000000000..b5fabf7da --- /dev/null +++ b/src/Refitter.Tests/Apizr/ApizrOptionsAdapterPipelineTests.cs @@ -0,0 +1,163 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class ApizrOptionsAdapterPipelineTests +{ + [Test] + public void Adapters_Combine_Cache_And_Mapping() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.Akavache, + WithMappingProvider = MappingProviderType.AutoMapper + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithAkavacheCacheHandler()"); + result.Should().Contain("WithAutoMapperMappingHandler()"); + result.Should().Contain("using Akavache;"); + result.Should().Contain("using AutoMapper;"); + result.Should().Contain("Apizr.Integrations.Akavache"); + result.Should().Contain("Apizr.Integrations.AutoMapper"); + } + + [Test] + public void Adapters_Combine_Retry_And_Mediation() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.Polly, + MaxRetryCount = 3, + FirstBackoffRetryInSeconds = 0.5 + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("AddPolicyHandler"); + result.Should().Contain("WithMediation()"); + result.Should().Contain("using Polly;"); + result.Should().Contain("using MediatR;"); + } + + [Test] + public void Pipeline_Order_Is_Correct() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.InMemory, + WithMappingProvider = MappingProviderType.AutoMapper, + WithPriority = true, + WithMediation = true, + WithFileTransfer = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + BaseUrl = "https://api.example.com", + HttpMessageHandlers = ["AuthHandler"], + TransientErrorHandler = TransientErrorHandler.Polly, + MaxRetryCount = 3, + FirstBackoffRetryInSeconds = 0.5 + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + // Base address + result.Should().Contain("WithBaseAddress(\"https://api.example.com\""); + // Message handlers + result.Should().Contain("WithDelegatingHandler()"); + // Retry + result.Should().Contain("AddPolicyHandler"); + // Cache + result.Should().Contain("WithInMemoryCacheHandler()"); + // Mapping + result.Should().Contain("WithAutoMapperMappingHandler()"); + // Priority + result.Should().Contain("WithPriority()"); + // Mediation + result.Should().Contain("WithMediation()"); + // File transfer + result.Should().Contain("WithFileTransferMediation()"); + result.Should().Contain("Apizr.Integrations.FileTransfer.MediatR"); + } + + [Test] + public void Pipeline_Produces_Compilable_Code_With_All_Features() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.Akavache, + WithMappingProvider = MappingProviderType.AutoMapper, + WithPriority = true, + WithMediation = true, + WithFileTransfer = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + BaseUrl = "https://api.example.com", + HttpMessageHandlers = ["AuthHandler"], + TransientErrorHandler = TransientErrorHandler.Polly, + MaxRetryCount = 3, + FirstBackoffRetryInSeconds = 0.5 + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().NotContain("/!\\ ERROR"); + result.Should().Contain("WithBaseAddress"); + result.Should().Contain("WithDelegatingHandler()"); + result.Should().Contain("AddPolicyHandler"); + result.Should().Contain("WithAkavacheCacheHandler()"); + result.Should().Contain("WithAutoMapperMappingHandler()"); + result.Should().Contain("WithPriority()"); + result.Should().Contain("WithMediation()"); + result.Should().Contain("Apizr.Integrations.FileTransfer.MediatR"); + } + + [Test] + public void Pipeline_Generates_Error_For_Extended_Features_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = true, + WithCacheProvider = CacheProviderType.InMemory + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("/!\\ ERROR"); + result.Should().Contain("DependencyInjectionSettings"); + } +} diff --git a/src/Refitter.Tests/Apizr/CacheProviderAdapterTests.cs b/src/Refitter.Tests/Apizr/CacheProviderAdapterTests.cs new file mode 100644 index 000000000..cd7b0b02a --- /dev/null +++ b/src/Refitter.Tests/Apizr/CacheProviderAdapterTests.cs @@ -0,0 +1,190 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class CacheProviderAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_CacheProvider_Is_Set() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.Akavache + } + }; + + var adapter = new CacheProviderAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_CacheProvider_Is_None() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.None + } + }; + + var adapter = new CacheProviderAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_Akavache_To_Options() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.Akavache + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithAkavacheCacheHandler()"); + result.Should().Contain("using Akavache;"); + result.Should().Contain("Apizr.Integrations.Akavache"); + } + + [Test] + public void Apply_Adds_MonkeyCache_To_Options() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.MonkeyCache + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithCacheHandler(new MonkeyCacheHandler(Barrel.Current))"); + result.Should().Contain("using MonkeyCache;"); + result.Should().Contain("Apizr.Integrations.MonkeyCache"); + } + + [Test] + public void Apply_Adds_InMemory_Only_With_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.InMemory + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithInMemoryCacheHandler()"); + } + + [Test] + public void Apply_Omits_InMemory_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.InMemory + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().NotContain("WithInMemoryCacheHandler()"); + } + + [Test] + public void Apply_Adds_DistributedAsString_Only_With_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.DistributedAsString + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithDistributedCacheHandler()"); + } + + [Test] + public void Apply_Omits_DistributedAsString_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.DistributedAsString + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().NotContain("WithDistributedCacheHandler()"); + } + + [Test] + public void Apply_Adds_DistributedAsByteArray_Only_With_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.DistributedAsByteArray + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithDistributedCacheHandler()"); + } + + [Test] + public void Apply_Omits_DistributedAsByteArray_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithCacheProvider = CacheProviderType.DistributedAsByteArray + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().NotContain("WithDistributedCacheHandler()"); + } +} diff --git a/src/Refitter.Tests/Apizr/FileTransferAdapterTests.cs b/src/Refitter.Tests/Apizr/FileTransferAdapterTests.cs new file mode 100644 index 000000000..2d8f2804c --- /dev/null +++ b/src/Refitter.Tests/Apizr/FileTransferAdapterTests.cs @@ -0,0 +1,99 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class FileTransferAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_FileTransfer_Enabled() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithFileTransfer = true + } + }; + + var adapter = new FileTransferAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_FileTransfer_Disabled() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithFileTransfer = false + } + }; + + var adapter = new FileTransferAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_FileTransferMediation_With_DI_And_Mediation() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithFileTransfer = true, + WithMediation = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithFileTransferMediation()"); + result.Should().Contain("Apizr.Integrations.FileTransfer.MediatR"); + } + + [Test] + public void Apply_Adds_FileTransfer_Package_With_DI_Without_Mediation() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithFileTransfer = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("Apizr.Extensions.Microsoft.FileTransfer"); + result.Should().NotContain("WithFileTransferMediation()"); + } + + [Test] + public void Apply_Adds_FileTransfer_Package_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithFileTransfer = true + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("Apizr.Integrations.FileTransfer"); + result.Should().NotContain("WithFileTransferMediation()"); + } +} diff --git a/src/Refitter.Tests/Apizr/HttpMessageHandlerAdapterTests.cs b/src/Refitter.Tests/Apizr/HttpMessageHandlerAdapterTests.cs new file mode 100644 index 000000000..924e3c572 --- /dev/null +++ b/src/Refitter.Tests/Apizr/HttpMessageHandlerAdapterTests.cs @@ -0,0 +1,67 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class HttpMessageHandlerAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_Handlers_Present() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + HttpMessageHandlers = ["AuthHandler"] + } + }; + + var adapter = new HttpMessageHandlerAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_No_Handlers() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var adapter = new HttpMessageHandlerAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void CanApply_Returns_False_When_No_DI_Settings() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true } + }; + + var adapter = new HttpMessageHandlerAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_DelegatingHandlers() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + HttpMessageHandlers = ["AuthHandler", "LoggingHandler"] + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithDelegatingHandler()"); + result.Should().Contain("WithDelegatingHandler()"); + } +} diff --git a/src/Refitter.Tests/Apizr/MappingProviderAdapterTests.cs b/src/Refitter.Tests/Apizr/MappingProviderAdapterTests.cs new file mode 100644 index 000000000..237e5dff1 --- /dev/null +++ b/src/Refitter.Tests/Apizr/MappingProviderAdapterTests.cs @@ -0,0 +1,123 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class MappingProviderAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_MappingProvider_Is_Set() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.AutoMapper + } + }; + + var adapter = new MappingProviderAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_MappingProvider_Is_None() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.None + } + }; + + var adapter = new MappingProviderAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_AutoMapper_With_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.AutoMapper + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithAutoMapperMappingHandler()"); + result.Should().NotContain("new MapperConfiguration"); + result.Should().Contain("using AutoMapper;"); + result.Should().Contain("Apizr.Integrations.AutoMapper"); + } + + [Test] + public void Apply_Adds_AutoMapper_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.AutoMapper + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithAutoMapperMappingHandler(new MapperConfiguration(config => { /* YOUR_MAPPINGS_HERE */ }))"); + result.Should().Contain("using AutoMapper;"); + } + + [Test] + public void Apply_Adds_Mapster_With_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.Mapster + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithMapsterMappingHandler()"); + result.Should().NotContain("new Mapper()"); + result.Should().Contain("using Mapster;"); + result.Should().Contain("using MapsterMapper;"); + result.Should().Contain("Apizr.Integrations.Mapster"); + } + + [Test] + public void Apply_Adds_Mapster_Without_DI() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMappingProvider = MappingProviderType.Mapster + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithMapsterMappingHandler(new Mapper())"); + result.Should().Contain("using Mapster;"); + result.Should().NotContain("using MapsterMapper;"); + } +} diff --git a/src/Refitter.Tests/Apizr/MediationAdapterTests.cs b/src/Refitter.Tests/Apizr/MediationAdapterTests.cs new file mode 100644 index 000000000..bd581f03a --- /dev/null +++ b/src/Refitter.Tests/Apizr/MediationAdapterTests.cs @@ -0,0 +1,78 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class MediationAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_Mediation_Enabled_With_DI() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var adapter = new MediationAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_Mediation_Disabled() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = false + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var adapter = new MediationAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void CanApply_Returns_False_When_Mediation_Enabled_Without_DI() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = true + } + }; + + var adapter = new MediationAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_Mediation_To_Options() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithMediation = true + }, + DependencyInjectionSettings = new DependencyInjectionSettings() + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithMediation()"); + result.Should().Contain("using MediatR;"); + result.Should().Contain("Apizr.Integrations.MediatR"); + } +} diff --git a/src/Refitter.Tests/Apizr/PriorityAdapterTests.cs b/src/Refitter.Tests/Apizr/PriorityAdapterTests.cs new file mode 100644 index 000000000..9d3ebc19c --- /dev/null +++ b/src/Refitter.Tests/Apizr/PriorityAdapterTests.cs @@ -0,0 +1,58 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class PriorityAdapterTests +{ + [Test] + public void CanApply_Returns_True_When_Priority_Enabled() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithPriority = true + } + }; + + var adapter = new PriorityAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_When_Priority_Disabled() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithPriority = false + } + }; + + var adapter = new PriorityAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_Priority_To_Options() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings + { + WithRegistrationHelper = true, + WithPriority = true + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("WithPriority()"); + result.Should().Contain("Apizr.Integrations.Fusillade"); + } +} diff --git a/src/Refitter.Tests/Apizr/RetryHandlerAdapterTests.cs b/src/Refitter.Tests/Apizr/RetryHandlerAdapterTests.cs new file mode 100644 index 000000000..4e9f3999c --- /dev/null +++ b/src/Refitter.Tests/Apizr/RetryHandlerAdapterTests.cs @@ -0,0 +1,115 @@ +using FluentAssertions; +using Refitter.Core; + +namespace Refitter.Tests.Apizr; + +public class RetryHandlerAdapterTests +{ + [Test] + public void CanApply_Returns_True_For_Polly() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.Polly + } + }; + + var adapter = new RetryHandlerAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_True_For_HttpResilience() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.HttpResilience + } + }; + + var adapter = new RetryHandlerAdapter(); + adapter.CanApply(settings).Should().BeTrue(); + } + + [Test] + public void CanApply_Returns_False_For_None() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.None + } + }; + + var adapter = new RetryHandlerAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void CanApply_Returns_False_When_No_DI_Settings() + { + var settings = new RefitGeneratorSettings + { + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true } + }; + + var adapter = new RetryHandlerAdapter(); + adapter.CanApply(settings).Should().BeFalse(); + } + + [Test] + public void Apply_Adds_Polly_Configuration() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.Polly, + MaxRetryCount = 3, + FirstBackoffRetryInSeconds = 0.5 + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("using Polly;"); + result.Should().Contain("using Polly.Extensions.Http;"); + result.Should().Contain("AddPolicyHandler"); + result.Should().Contain("Backoff.DecorrelatedJitterBackoffV2"); + result.Should().Contain("TimeSpan.FromSeconds(0.5)"); + result.Should().Contain("3"); + } + + [Test] + public void Apply_Adds_HttpResilience_Configuration() + { + var settings = new RefitGeneratorSettings + { + Namespace = "TestNamespace", + ApizrSettings = new ApizrSettings { WithRegistrationHelper = true }, + DependencyInjectionSettings = new DependencyInjectionSettings + { + TransientErrorHandler = TransientErrorHandler.HttpResilience, + MaxRetryCount = 5, + FirstBackoffRetryInSeconds = 1.0 + } + }; + + var result = ApizrRegistrationGenerator.Generate(settings, ["ITestApi"], "Test API"); + + result.Should().Contain("using Microsoft.Extensions.Http.Resilience;"); + result.Should().Contain("AddStandardResilienceHandler"); + result.Should().Contain("MaxRetryAttempts = 5"); + result.Should().Contain("TimeSpan.FromSeconds(1)"); + } +}