fix(central-ui): Debug View reconnect guards the stored instance; drop select-era sort; deep-link-in-area test

Three final-review findings on the two picker pages:

1. DebugView's localStorage auto-reconnect restored the stored instance id with
   no membership check, where the ?instanceId= path has one — a stored instance
   that is no longer Enabled (or was deleted, or moved sites) is filtered out of
   the list the picker is handed, so the field rendered blank while the page held
   a non-zero id and auto-connected to it anyway. The guard now mirrors the
   deep-link path: forget the stored instance id, tell the operator, and leave the
   site selected and loaded so they can pick again.
2. FlowDebugger's _instances kept an OrderBy(UniqueName) from the flat <select>
   era; InstanceTreeBuilder sorts areas and instances itself.
3. The deep-link test is joined by one where the instance sits two areas deep, so
   the field text is pinned to resolve from the flat list with the panel never
   opened.

Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
Joseph Doherty
2026-09-08 10:01:22 -04:00
parent 82f6fb949e
commit 52726cf30d
4 changed files with 77 additions and 5 deletions
@@ -186,6 +186,31 @@ public class DebugViewInstancePickerTests : BunitContext
Assert.False(cut.Find("[data-test='debug-instance-input']").HasAttribute("disabled")));
}
/// <summary>
/// The localStorage auto-reconnect must apply the same membership guard the
/// <c>?instanceId=</c> deep link does. Off01 is Disabled, so the page filters it out of the
/// list the picker is handed — restoring it anyway left the field blank while the page held
/// a non-zero id and auto-connected to it. The stored id is dropped instead, and the site
/// stays selected and loaded so the operator can pick again.
/// </summary>
[Fact]
public void AutoReconnect_FromStorage_SkipsAnInstanceThatIsNoLongerAvailable()
{
RegisterServices();
JSInterop.Setup<string>("localStorage.getItem", "debugView.siteId").SetResult(SiteId.ToString());
JSInterop.Setup<string>("localStorage.getItem", "debugView.instanceId").SetResult("8");
var cut = Render<DebugViewPage>();
cut.WaitForAssertion(() =>
Assert.Equal(string.Empty, cut.Find("[data-test='debug-instance-input']").GetAttribute("value")));
// Nothing is selected, so Connect stays disabled — and the stale id is forgotten.
var connect = cut.FindAll("button.btn.btn-primary.btn-sm").First(b => b.TextContent.Contains("Connect"));
Assert.True(connect.HasAttribute("disabled"));
JSInterop.VerifyInvoke("localStorage.removeItem");
}
[Fact]
public void WhileConnected_ThePickerIsDisabled()
{