using Xunit; namespace Admin.NET.Plugin.AiDOP.Tests.Infrastructure; public class AidopMenuLinkSyncContractTests { [Fact] public void StartupSync_MaintainsTenantMenus_ButNeverReconcilesRoleMenus() { var source = File.ReadAllText(FindSourceFile()); var ensureLinked = ExtractMethod(source, "public static void EnsureLinked(IServiceProvider services)"); Assert.Contains("SysTenantMenu", ensureLinked); Assert.DoesNotContain("SysRoleMenu", ensureLinked); } private static string ExtractMethod(string source, string signature) { var signatureIndex = source.IndexOf(signature, StringComparison.Ordinal); Assert.True(signatureIndex >= 0, $"Method not found: {signature}"); var bodyStart = source.IndexOf('{', signatureIndex); Assert.True(bodyStart >= 0, $"Method body not found: {signature}"); var depth = 0; for (var i = bodyStart; i < source.Length; i++) { if (source[i] == '{') depth++; if (source[i] != '}') continue; depth--; if (depth == 0) return source[signatureIndex..(i + 1)]; } throw new InvalidOperationException($"Method body is incomplete: {signature}"); } private static string FindSourceFile() { var directory = new DirectoryInfo(AppContext.BaseDirectory); while (directory != null) { var candidate = Path.Combine( directory.FullName, "server", "Plugins", "Admin.NET.Plugin.AiDOP", "Infrastructure", "AidopMenuLinkSync.cs"); if (File.Exists(candidate)) return candidate; directory = directory.Parent; } throw new FileNotFoundException("AidopMenuLinkSync.cs not found from test output path."); } }