using Xunit; namespace Admin.NET.Plugin.AiDOP.Tests.SmartOps; public class SmartOpsImprovementLedgerTests { [Fact] public void FuncCode_S9_017_IsRegisteredOnce() { var source = File.ReadAllText(FindFile("Web", "src", "constants", "aidopFuncCodes.ts")); Assert.Contains("FUNC-S9-017", source); Assert.Contains("改善计划台账", source); Assert.Equal(1, Count(source, "FUNC-S9-017")); Assert.DoesNotContain("Title = \"FUNC-S9-017", File.ReadAllText(FindFile( "server", "Plugins", "Admin.NET.Plugin.AiDOP", "SeedData", "SysMenuSeedData.cs"))); } [Fact] public void LedgerApi_FiltersAndExportStayTenantScoped() { var source = File.ReadAllText(FindFile( "server", "Plugins", "Admin.NET.Plugin.AiDOP", "Controllers", "AdoSmartOpsImprovementPlanController.cs")); Assert.Contains("ApplyLedgerFilter", source); Assert.Contains("input.Overdue", source); Assert.Contains("input.AutoVerifyResult", source); Assert.Contains("[HttpPost(\"export\")]", source); Assert.Contains("x.TenantId == tenantId", source); Assert.Contains("ledgerLogs", source); } private static int Count(string source, string token) { var n = 0; for (var i = 0; (i = source.IndexOf(token, i, StringComparison.Ordinal)) >= 0; i += token.Length) n++; return n; } private static string FindFile(params string[] parts) { var dir = new DirectoryInfo(AppContext.BaseDirectory); while (dir != null) { var candidate = Path.Combine(new[] { dir.FullName }.Concat(parts).ToArray()); if (File.Exists(candidate)) return candidate; dir = dir.Parent; } throw new FileNotFoundException(string.Join("/", parts)); } }