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.");
}
}