Files
ROLAC/API/ROLAC.API.Tests/Services/DbSeederForm990Tests.cs
T
2026-06-24 19:21:04 -07:00

81 lines
3.4 KiB
C#

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.Entities;
using Xunit;
namespace ROLAC.API.Tests.Services;
public class DbSeederForm990Tests
{
private static AppDbContext BuildDb()
{
var ctx = new DefaultHttpContext { User = new(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "seed") })) };
var mock = new Mock<IHttpContextAccessor>();
mock.Setup(x => x.HttpContext).Returns(ctx);
return new AppDbContext(new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.AddInterceptors(new AuditSaveChangesInterceptor(new ROLAC.API.Services.Logging.CurrentUserAccessor(mock.Object))).Options);
}
[Fact]
public async Task SeedExpenseCategories_AddsNewGroups_RenamesDuplicates_AndIsIdempotent()
{
using var db = BuildDb();
var fnb = new ExpenseCategoryGroup { Name_en = "Food & Beverage", Name_zh = "餐飲", SortOrder = 3 };
db.ExpenseCategoryGroups.Add(fnb);
await db.SaveChangesAsync();
db.ExpenseSubCategories.Add(new ExpenseSubCategory { GroupId = fnb.Id, Name_en = "Consumables", Name_zh = "消耗品" });
await db.SaveChangesAsync();
await DbSeeder.SeedExpenseCategoriesAsync(db);
await DbSeeder.SeedExpenseCategoriesAsync(db); // idempotent second run
var groups = await db.ExpenseCategoryGroups.ToListAsync();
Assert.Contains(groups, g => g.Name_en == "Professional Services");
Assert.Contains(groups, g => g.Name_en == "Information Technology");
Assert.Contains(groups, g => g.Name_en == "Finance & Banking");
var fnbSubs = await db.ExpenseSubCategories.Where(s => s.GroupId == fnb.Id).ToListAsync();
Assert.DoesNotContain(fnbSubs, s => s.Name_en == "Consumables");
Assert.Contains(fnbSubs, s => s.Name_en == "Disposable Tableware");
Assert.Single(groups, g => g.Name_en == "Professional Services");
}
[Fact]
public async Task SeedMinistries_SetsAdministrationToManagementGeneral_OthersProgram()
{
using var db = BuildDb();
await DbSeeder.SeedMinistriesAsync(db);
var admin = await db.Ministries.FirstAsync(m => m.Name_en == "Administration");
var worship = await db.Ministries.FirstAsync(m => m.Name_en == "Worship");
Assert.Equal("ManagementGeneral", admin.DefaultFunctionalClass);
Assert.Equal("Program", worship.DefaultFunctionalClass);
}
[Fact]
public async Task SeedForm990Lines_CreatesCatalog_AndMapsKnownSubcategories()
{
using var db = BuildDb();
await DbSeeder.SeedExpenseCategoriesAsync(db);
await DbSeeder.SeedForm990ExpenseLinesAsync(db);
await DbSeeder.SeedForm990ExpenseLinesAsync(db); // idempotent
Assert.Equal(1, await db.Form990ExpenseLines.CountAsync(l => l.LineCode == "7"));
Assert.True(await db.Form990ExpenseLines.AnyAsync(l => l.LineCode == "24"));
var salary = await db.ExpenseSubCategories.Include(s => s.Form990Line)
.FirstAsync(s => s.Name_en == "Salary & Wages");
Assert.Equal("7", salary.Form990Line!.LineCode);
var audit = await db.ExpenseSubCategories.Include(s => s.Form990Line)
.FirstAsync(s => s.Name_en == "Accounting & Audit");
Assert.Equal("11c", audit.Form990Line!.LineCode);
}
}