69 lines
2.9 KiB
C#
69 lines
2.9 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 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);
|
|
}
|
|
}
|