fix(centralui): NodeBrowserDialog — reset load/expand spinner on error + clear stale failure on blank search (T15)

This commit is contained in:
Joseph Doherty
2026-06-18 03:05:23 -04:00
parent 733c7bf66c
commit 45a5a92455
2 changed files with 49 additions and 5 deletions
@@ -211,8 +211,15 @@
{ {
node.Loading = true; node.Loading = true;
StateHasChanged(); StateHasChanged();
var result = await BrowseService.BrowseChildrenAsync(_runtimeSiteId, _runtimeConnectionName, node.NodeId); BrowseNodeResult result;
node.Loading = false; try
{
result = await BrowseService.BrowseChildrenAsync(_runtimeSiteId, _runtimeConnectionName, node.NodeId);
}
finally
{
node.Loading = false;
}
if (result.Failure is not null) if (result.Failure is not null)
{ {
@@ -237,9 +244,16 @@
node.Loading = true; node.Loading = true;
StateHasChanged(); StateHasChanged();
var result = await BrowseService.BrowseChildrenAsync( BrowseNodeResult result;
_runtimeSiteId, _runtimeConnectionName, node.NodeId, node.ContinuationToken); try
node.Loading = false; {
result = await BrowseService.BrowseChildrenAsync(
_runtimeSiteId, _runtimeConnectionName, node.NodeId, node.ContinuationToken);
}
finally
{
node.Loading = false;
}
if (result.Failure is not null) if (result.Failure is not null)
{ {
@@ -266,6 +280,8 @@
_searchActive = false; _searchActive = false;
_searchResults = new(); _searchResults = new();
_searchCapReached = false; _searchCapReached = false;
_failure = null;
_failureMessage = "";
StateHasChanged(); StateHasChanged();
return; return;
} }
@@ -124,4 +124,32 @@ public class NodeBrowserDialogSearchTests : BunitContext
cut.Find("[data-test=node-search-button]").Click(); cut.Find("[data-test=node-search-button]").Click();
Assert.Empty(cut.FindAll("[data-test=node-search-result]")); Assert.Empty(cut.FindAll("[data-test=node-search-result]"));
} }
[Fact]
public void BlankQueryAfterFailure_ClearsStaleFailureAlert()
{
// First search returns a failure so the alert banner appears.
_browse.SearchAsync(
Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>())
.Returns(new SearchAddressSpaceResult(
Matches: Array.Empty<AddressSpaceMatch>(),
CapReached: false,
Failure: new BrowseFailure(BrowseFailureKind.Timeout, "timed out")));
var cut = RenderShown(out _);
cut.Find("[data-test=node-search-input]").Input("Pump1");
cut.Find("[data-test=node-search-button]").Click();
// The failure alert must be visible after the failed search.
Assert.NotEmpty(cut.FindAll(".alert-danger"));
// User clears the query and searches again (blank).
cut.Find("[data-test=node-search-input]").Input("");
cut.Find("[data-test=node-search-button]").Click();
// Stale failure alert must be gone.
Assert.Empty(cut.FindAll(".alert-danger"));
}
} }