using FluentAssertions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using SIGCM2.Application.Audit; using SIGCM2.Infrastructure; using Xunit; namespace SIGCM2.Application.Tests.Infrastructure.Audit; /// UDT-010 Batch 3 — AuditOptions binding smoke tests. /// Validates that AddInfrastructure binds AuditOptions from the "Audit" config section /// and falls back to the POCO defaults when the section is absent. public sealed class AuditOptionsBindingTests { private static IServiceProvider BuildProvider(IEnumerable>? overrides = null) { // Minimum required config for AddInfrastructure to succeed. var inMemory = new Dictionary { ["ConnectionStrings:SqlServer"] = "Server=nowhere;Database=x;Integrated Security=true;", ["Jwt:Issuer"] = "test", ["Jwt:Audience"] = "test", ["Jwt:AccessTokenMinutes"] = "60", ["Jwt:RefreshTokenDays"] = "7", ["Jwt:PrivateKeyPath"] = "unused-in-this-test.pem", ["Jwt:PublicKeyPath"] = "unused-in-this-test.pem", }; if (overrides is not null) foreach (var kv in overrides) inMemory[kv.Key] = kv.Value; var config = new ConfigurationBuilder().AddInMemoryCollection(inMemory).Build(); var services = new ServiceCollection(); services.AddInfrastructure(config); return services.BuildServiceProvider(); } [Fact] public void AuditOptions_WithoutConfigSection_UsesPocoDefaults() { using var sp = (ServiceProvider)BuildProvider(); var opts = sp.GetRequiredService>().Value; opts.SanitizedKeys.Should().Contain("password"); opts.SanitizedKeys.Should().Contain("refreshToken"); opts.SanitizedKeys.Should().Contain("apiKey"); } [Fact] public void AuditOptions_WithConfigSection_AddsToDefaults_PerIConfigurationArrayBinding() { // IConfiguration array binding is ADDITIVE, not REPLACE: config values at indices 0..N // overwrite those indices but defaults beyond N are preserved. This is intended for // AuditOptions — extensibility is additive (append, not replace). using var sp = (ServiceProvider)BuildProvider(new[] { new KeyValuePair("Audit:SanitizedKeys:11", "customSecret"), new KeyValuePair("Audit:SanitizedKeys:12", "internalToken"), }); var opts = sp.GetRequiredService>().Value; // The 11 defaults remain + the 2 extras appear at the configured indices. opts.SanitizedKeys.Should().Contain("password"); // default survived opts.SanitizedKeys.Should().Contain("customSecret"); // appended via config opts.SanitizedKeys.Should().Contain("internalToken"); // appended via config } }