feat(centralui): Topology pre-loads and expands the first layer (sites -> top-level areas) (Gitea #39)
This commit is contained in:
@@ -244,6 +244,55 @@ public class TopologyPageTests : BunitContext
|
||||
_repo.DidNotReceive().GetAllTemplatesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>Gitea #39: the first layer (areas of every permitted site) is loaded at open; instances stay lazy.</summary>
|
||||
[Fact]
|
||||
public void InitialLoad_PreloadsAreasForPermittedSites_ButNoInstances()
|
||||
{
|
||||
SeedRepos(sites: [new Site("Plant", "plant") { Id = 1 }, new Site("Yard", "yard") { Id = 2 }],
|
||||
areasBySite: new()
|
||||
{
|
||||
[1] = new List<Area> { new("Line A") { Id = 10, SiteId = 1 } },
|
||||
[2] = new List<Area> { new("Dock") { Id = 20, SiteId = 2 } },
|
||||
});
|
||||
var cut = Render<TopologyPage>();
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("Line A", cut.Markup);
|
||||
Assert.Contains("Dock", cut.Markup);
|
||||
});
|
||||
_repo.DidNotReceive().GetTopologyInstancesAsync(Arg.Any<int>(), Arg.Any<int?>(), Arg.Any<int>(), Arg.Any<int>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>Gitea #39: a site outside the user's scope never has its areas read.</summary>
|
||||
[Fact]
|
||||
public async Task InitialLoad_OutOfScopeSite_AreasNeverRead()
|
||||
{
|
||||
SeedRepos(sites: [new Site("Plant", "plant") { Id = 1 }, new Site("Yard", "yard") { Id = 2 }],
|
||||
areasBySite: new()
|
||||
{
|
||||
[1] = new List<Area> { new("Line A") { Id = 10, SiteId = 1 } },
|
||||
[2] = new List<Area> { new("Dock") { Id = 20, SiteId = 2 } },
|
||||
});
|
||||
var auth = Services.GetRequiredService<AuthenticationStateProvider>();
|
||||
var identity = (ClaimsIdentity)(await auth.GetAuthenticationStateAsync()).User.Identity!;
|
||||
identity.AddClaim(new Claim(JwtTokenService.SiteIdClaimType, "1"));
|
||||
var cut = Render<TopologyPage>();
|
||||
cut.WaitForAssertion(() => Assert.Contains("Line A", cut.Markup));
|
||||
Assert.DoesNotContain("Dock", cut.Markup);
|
||||
await _repo.DidNotReceive().GetAreasBySiteIdAsync(2, Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>Gitea #39: with no saved expansion state sites open; a saved (collapsed) state wins.</summary>
|
||||
[Fact]
|
||||
public void InitialLoad_SitesExpanded_WhenNoSavedState_AndSavedStateWins()
|
||||
{
|
||||
SeedRepos(sites: [new Site("Plant", "plant") { Id = 1 }],
|
||||
areasBySite: new() { [1] = new List<Area> { new("Line A") { Id = 10, SiteId = 1 } } });
|
||||
var cut = Render<TopologyPage>();
|
||||
cut.WaitForAssertion(() => Assert.Contains("Line A", cut.Markup));
|
||||
Assert.Contains("aria-expanded=\"true\"", cut.Markup);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that moving an existing topology item uses the current site scope.</summary>
|
||||
/// <param name="revoked">Whether the user's site permission has been revoked.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
@@ -343,7 +392,6 @@ public class TopologyPageTests : BunitContext
|
||||
// Expand the site, then the area, to render the instance leaf. The
|
||||
// helper scopes by the row's own label so we don't match outer rows
|
||||
// whose TextContent transitively contains the inner label.
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
FindToggleForLabel(cut, "Line-1")!.Click();
|
||||
|
||||
Assert.Contains("Pump-001", cut.Markup);
|
||||
@@ -369,7 +417,6 @@ public class TopologyPageTests : BunitContext
|
||||
areasBySite: areasBySite);
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
|
||||
var search = cut.Find("input[type='text']");
|
||||
search.Input("Line");
|
||||
@@ -440,7 +487,6 @@ public class TopologyPageTests : BunitContext
|
||||
SeedRepos(sites: new[] { new Site("Plant-A", "plant-a") { Id = 1 } }, areasBySite: areasBySite);
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
|
||||
var areaLabel = cut.FindAll("span.tv-label").First(s => s.TextContent == "Line-1");
|
||||
areaLabel.DoubleClick();
|
||||
@@ -464,7 +510,6 @@ public class TopologyPageTests : BunitContext
|
||||
_repo.GetAreaByIdAsync(10, Arg.Any<CancellationToken>()).Returns(area);
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
cut.FindAll("span.tv-label").First(s => s.TextContent == "Line-1").DoubleClick();
|
||||
|
||||
var input = cut.Find("input[aria-label='Rename Line-1']");
|
||||
@@ -491,7 +536,6 @@ public class TopologyPageTests : BunitContext
|
||||
});
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
|
||||
var instanceLabel = cut.FindAll("span.tv-label").First(s => s.TextContent == "Pump-001");
|
||||
Assert.Throws<Bunit.MissingEventHandlerException>(() => instanceLabel.DoubleClick());
|
||||
@@ -560,7 +604,6 @@ public class TopologyPageTests : BunitContext
|
||||
new FlatteningPipelineResult(currentConfig, "hash-new", ValidationResult.Success()))));
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
FindToggleForLabel(cut, "Line-1")!.Click();
|
||||
|
||||
// The per-node action menu only renders after a context-menu (right
|
||||
@@ -646,7 +689,6 @@ public class TopologyPageTests : BunitContext
|
||||
SeedOneDeployedInstanceWithComparison();
|
||||
|
||||
var cut = RenderLoadedTopology();
|
||||
FindToggleForLabel(cut, "Plant-A")!.Click();
|
||||
|
||||
Assert.Contains("Pump-001", cut.Markup);
|
||||
Assert.Contains("Enabled", cut.Markup);
|
||||
|
||||
Reference in New Issue
Block a user