0308490aef
Resolves the remaining Minor items from the 2026-05-15 review so the web-UI dashboard work has no open follow-ups: a real-HubConnection end-to-end test for the SignalR feed, stable mbproxy.admin.broadcast.* log-event names, keyboard/aria accessibility on the fleet table, frontend JS hardening (URL-decode guard, NaN guards, shared util.js), reconciler<->capture-registry coverage, throwing-sink and embedded-asset tests, broadcaster polish, and a soft upper bound on AdminPushIntervalMs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
64 lines
2.3 KiB
C#
64 lines
2.3 KiB
C#
using System.Reflection;
|
|
using Mbproxy.Admin;
|
|
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace Mbproxy.Tests.Admin;
|
|
|
|
/// <summary>
|
|
/// Guards the <c>Admin\wwwroot\*.*</c> embedded-resource glob in <c>Mbproxy.csproj</c>.
|
|
/// 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.
|
|
/// </summary>
|
|
[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");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks up from the test assembly directory to the repo and returns
|
|
/// <c>src/Mbproxy/Admin/wwwroot</c> — same upward-search pattern the simulator
|
|
/// fixture uses to find <c>tests/sim</c>.
|
|
/// </summary>
|
|
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.");
|
|
}
|
|
}
|