using Microsoft.EntityFrameworkCore; using System.Security.Claims; using Microsoft.AspNetCore.Http; using Moq; using ROLAC.API.Data; using ROLAC.API.Data.Interceptors; using ROLAC.API.DTOs.Giving; using ROLAC.API.Services; using Xunit; namespace ROLAC.API.Tests.Services; public class GivingCategoryServiceTests { private static IHttpContextAccessor BuildAccessor(string userId = "test-user") { var claims = new[] { new Claim(ClaimTypes.NameIdentifier, userId) }; var ctx = new DefaultHttpContext { User = new(new ClaimsIdentity(claims)) }; var mock = new Mock(); mock.Setup(x => x.HttpContext).Returns(ctx); return mock.Object; } private static AppDbContext BuildDb(string userId = "test-user") { var interceptor = new AuditSaveChangesInterceptor(new ROLAC.API.Services.Logging.CurrentUserAccessor(BuildAccessor(userId))); return new AppDbContext( new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .AddInterceptors(interceptor) .Options); } [Fact] public async Task CreateAsync_ReturnsId_AndDefaultsActive() { using var db = BuildDb(); var svc = new GivingCategoryService(db); var id = await svc.CreateAsync(new CreateGivingCategoryRequest { Name_en = "Tithe", Name_zh = "什一" }); var saved = await db.GivingCategories.FindAsync(id); Assert.NotNull(saved); Assert.True(saved!.IsActive); Assert.Equal("Tithe", saved.Name_en); } [Fact] public async Task GetAllAsync_ExcludesInactive_ByDefault() { using var db = BuildDb(); var svc = new GivingCategoryService(db); var id1 = await svc.CreateAsync(new CreateGivingCategoryRequest { Name_en = "Active" }); var id2 = await svc.CreateAsync(new CreateGivingCategoryRequest { Name_en = "Gone" }); await svc.DeactivateAsync(id2); var active = await svc.GetAllAsync(includeInactive: false); var all = await svc.GetAllAsync(includeInactive: true); Assert.Single(active); Assert.Equal(2, all.Count); } [Fact] public async Task DeactivateAsync_SetsIsActiveFalse() { using var db = BuildDb(); var svc = new GivingCategoryService(db); var id = await svc.CreateAsync(new CreateGivingCategoryRequest { Name_en = "Temp" }); await svc.DeactivateAsync(id); var saved = await db.GivingCategories.FindAsync(id); Assert.False(saved!.IsActive); } [Fact] public async Task UpdateAsync_Throws_WhenMissing() { using var db = BuildDb(); var svc = new GivingCategoryService(db); await Assert.ThrowsAsync(() => svc.UpdateAsync(999, new UpdateGivingCategoryRequest { Name_en = "X" })); } [Fact] public async Task DeactivateAsync_Throws_WhenMissing() { using var db = BuildDb(); var svc = new GivingCategoryService(db); await Assert.ThrowsAsync(() => svc.DeactivateAsync(999)); } }