using System.Security.Claims; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging.Abstractions; using Moq; using ROLAC.API.Data; using ROLAC.API.Data.Interceptors; using ROLAC.API.Entities; using ROLAC.API.Services.Ai; using ROLAC.API.Services.Logging; using Xunit; namespace ROLAC.API.Tests.Services; public class ExpenseCategoryAiServiceFactoryTests { // ChurchProfile is auditable, so the InMemory store rejects saves unless the // required CreatedBy/UpdatedBy fields are populated. Wire the same audit // interceptor the app uses so seeded entities save cleanly. private static AppDbContext NewDb() { var httpContext = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "test-user") })), }; var httpContextAccessor = new Mock(); httpContextAccessor.Setup(accessor => accessor.HttpContext).Returns(httpContext); return new AppDbContext(new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .ConfigureWarnings(warnings => warnings.Ignore(InMemoryEventId.TransactionIgnoredWarning)) .AddInterceptors(new AuditSaveChangesInterceptor(new CurrentUserAccessor(httpContextAccessor.Object))) .Options); } private static ExpenseCategoryAiServiceFactory Build(AppDbContext db) { var cfg = new ChurchAiConfigProvider(db); var claude = new ClaudeExpenseCategoryAiService( new HttpClient(), cfg, db, NullLogger.Instance); var gemini = new GeminiExpenseCategoryAiService( new HttpClient(), cfg, db, NullLogger.Instance); return new ExpenseCategoryAiServiceFactory(cfg, claude, gemini); } [Fact] public async Task Resolves_Claude_by_default() { using var db = NewDb(); db.ChurchProfiles.Add(new ChurchProfile { Name = "C", AiProvider = "Claude" }); await db.SaveChangesAsync(); var svc = await Build(db).ResolveAsync(); Assert.IsType(svc); } [Fact] public async Task Resolves_Gemini_when_selected() { using var db = NewDb(); db.ChurchProfiles.Add(new ChurchProfile { Name = "C", AiProvider = "Gemini" }); await db.SaveChangesAsync(); var svc = await Build(db).ResolveAsync(); Assert.IsType(svc); } }