fix(adminui): register the /dev/context-menu-demo route only in DEBUG builds (R04 S7)
The dev-only demo page shipped routable in the production assembly. Its route moves from @page to a code-behind [Route] under #if DEBUG, so a Release build keeps the component type (nothing referencing it breaks) but has no /dev/* route. The page-authorization guard classifies it under #if DEBUG, and DevRouteGatingTests asserts each configuration's half (Debug: exactly the demo route; Release: none) with a positive control. Both configurations pass. Refs #745 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
@page "/dev/context-menu-demo"
|
||||
@* The /dev/context-menu-demo route lives in ContextMenuDemo.razor.cs behind #if DEBUG (R04 S7), so a
|
||||
Release build ships the component but no route to it. *@
|
||||
@* Dev-only host page to live-verify the reusable ContextMenu component. *@
|
||||
@attribute [Authorize(Policy = AdminUiPolicies.AuthenticatedRead)]
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Dev;
|
||||
|
||||
/// <summary>
|
||||
/// Dev-only host page that live-verifies the reusable <c>ContextMenu</c> component. The route is
|
||||
/// compiled only into DEBUG builds (R04 S7): a Release (production) build keeps the component type —
|
||||
/// so nothing that references it breaks — but registers no <c>/dev/*</c> route, and the router never
|
||||
/// serves it.
|
||||
/// </summary>
|
||||
#if DEBUG
|
||||
[Microsoft.AspNetCore.Components.Route(RoutePath)]
|
||||
#endif
|
||||
public partial class ContextMenuDemo
|
||||
{
|
||||
/// <summary>The DEBUG-only route.</summary>
|
||||
public const string RoutePath = "/dev/context-menu-demo";
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Components;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Authorization;
|
||||
|
||||
/// <summary>
|
||||
/// R04 S7: <c>/dev/*</c> routes exist only in DEBUG builds. The test project builds in the same
|
||||
/// configuration as the AdminUI assembly, so each configuration asserts its own half — run
|
||||
/// <c>dotnet test -c Release</c> to exercise the production half.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class DevRouteGatingTests
|
||||
{
|
||||
private static IReadOnlyList<string> DevRoutes() =>
|
||||
typeof(Routes).Assembly.GetTypes()
|
||||
.SelectMany(t => t.GetCustomAttributes<RouteAttribute>(inherit: false))
|
||||
.Select(r => r.Template)
|
||||
.Where(t => t.StartsWith("/dev/", StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
|
||||
[Fact]
|
||||
public void Dev_routes_follow_the_build_configuration()
|
||||
{
|
||||
#if DEBUG
|
||||
DevRoutes().ShouldBe([ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Dev.ContextMenuDemo.RoutePath]);
|
||||
#else
|
||||
DevRoutes().ShouldBeEmpty();
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Production_routes_are_present_in_every_configuration()
|
||||
{
|
||||
// Positive control: the scan sees routes at all (an empty assembly scan would pass the Release half).
|
||||
typeof(Routes).Assembly.GetTypes()
|
||||
.SelectMany(t => t.GetCustomAttributes<RouteAttribute>(inherit: false))
|
||||
.Select(r => r.Template)
|
||||
.ShouldContain("/hosts");
|
||||
}
|
||||
}
|
||||
+3
@@ -59,7 +59,10 @@ public class PageAuthorizationGuardTests
|
||||
|
||||
// ── AuthenticatedRead (17): dashboards, lists, live tails (read-only) + the dev ContextMenu demo ──
|
||||
[typeof(Home)] = AdminUiPolicies.AuthenticatedRead,
|
||||
#if DEBUG
|
||||
// Routable only in DEBUG builds (R04 S7) — a Release build registers no /dev/* route.
|
||||
[typeof(global::ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Dev.ContextMenuDemo)] = AdminUiPolicies.AuthenticatedRead,
|
||||
#endif
|
||||
[typeof(Fleet)] = AdminUiPolicies.AuthenticatedRead,
|
||||
[typeof(global::ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.FleetDiagnostics)] = AdminUiPolicies.AuthenticatedRead,
|
||||
[typeof(global::ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Hosts)] = AdminUiPolicies.AuthenticatedRead,
|
||||
|
||||
Reference in New Issue
Block a user