using System.Reflection; using Mbproxy.Admin; using Shouldly; using Xunit; namespace Mbproxy.Tests.Admin; /// /// Guards the Admin\wwwroot\*.* embedded-resource glob in Mbproxy.csproj. /// A broken or narrowed glob would silently drop a UI asset from the single-file binary; /// the admin endpoint would then 404 it at runtime with no compile-time failure. This /// test fails the build instead by comparing the on-disk source folder against the /// assembly's manifest resources. /// [Trait("Category", "Unit")] public sealed class EmbeddedAssetsTests { private const string ResourcePrefix = "Mbproxy.Admin.wwwroot."; [Fact] public void EveryWwwrootFile_IsEmbeddedAsAManifestResource() { var sourceDir = LocateWwwrootSource(); var sourceFiles = Directory.GetFiles(sourceDir) .Select(Path.GetFileName) .Where(n => n is not null) .Select(n => n!) .ToArray(); sourceFiles.ShouldNotBeEmpty("the source wwwroot folder should contain UI assets"); var embedded = typeof(StatusHub).Assembly .GetManifestResourceNames() .Where(n => n.StartsWith(ResourcePrefix, StringComparison.Ordinal)) .ToHashSet(StringComparer.Ordinal); foreach (var file in sourceFiles) { embedded.ShouldContain(ResourcePrefix + file, $"wwwroot asset '{file}' is not embedded — check the EmbeddedResource glob in Mbproxy.csproj"); } } /// /// Walks up from the test assembly directory to the repo and returns /// src/Mbproxy/Admin/wwwroot — same upward-search pattern the simulator /// fixture uses to find tests/sim. /// private static string LocateWwwrootSource() { var dir = new DirectoryInfo( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "."); while (dir is not null) { var candidate = Path.Combine(dir.FullName, "src", "Mbproxy", "Admin", "wwwroot"); if (Directory.Exists(candidate)) return candidate; dir = dir.Parent; } throw new DirectoryNotFoundException( "Could not locate src/Mbproxy/Admin/wwwroot above the test assembly."); } }