using Microsoft.Playwright; namespace ScadaLink.CentralUI.PlaywrightTests; /// /// E2E tests for the collapsible sidebar nav sections: sections are collapsed /// by default, a header toggle reveals a section's items, the state persists in /// the scadabridge_nav cookie across a full page reload, and navigating /// into a section auto-expands it. /// [Collection("Playwright")] public class NavCollapseTests { private readonly PlaywrightFixture _fixture; public NavCollapseTests(PlaywrightFixture fixture) { _fixture = fixture; } [Fact] public async Task Sections_AreCollapsedByDefault_AfterLogin() { var page = await _fixture.NewAuthenticatedPageAsync(); // The dashboard is sectionless, so no section is auto-expanded and the // cookie is empty on a fresh context — every section toggle is collapsed. await Expect(page.Locator("button.nav-section-toggle[aria-expanded='true']")) .ToHaveCountAsync(0); // A sectioned link is therefore absent from the DOM. Assert.Equal(0, await page.Locator("nav a:has-text('Topology')").CountAsync()); } [Fact] public async Task ClickingSectionHeader_RevealsItsItems() { var page = await _fixture.NewAuthenticatedPageAsync(); var toggle = page.Locator("button.nav-section-toggle:has-text('Deployment')"); Assert.Equal(0, await page.Locator("nav a:has-text('Topology')").CountAsync()); await toggle.ClickAsync(); await Expect(toggle).ToHaveAttributeAsync("aria-expanded", "true"); await Expect(page.GetByRole(AriaRole.Link, new() { Name = "Topology" })) .ToBeVisibleAsync(); } [Fact] public async Task CollapseState_SurvivesPageReload() { var page = await _fixture.NewAuthenticatedPageAsync(); await page.Locator("button.nav-section-toggle:has-text('Deployment')").ClickAsync(); await Expect(page.GetByRole(AriaRole.Link, new() { Name = "Topology" })) .ToBeVisibleAsync(); await page.ReloadAsync(); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); // The scadabridge_nav cookie restored the expanded Deployment section. await Expect(page.Locator("button.nav-section-toggle:has-text('Deployment')")) .ToHaveAttributeAsync("aria-expanded", "true"); await Expect(page.GetByRole(AriaRole.Link, new() { Name = "Topology" })) .ToBeVisibleAsync(); } [Fact] public async Task NavigatingIntoCollapsedSection_AutoExpandsIt() { var page = await _fixture.NewAuthenticatedPageAsync(); var auditToggle = page.Locator("button.nav-section-toggle:has-text('Audit')"); // The Audit section starts collapsed. await Expect(auditToggle).ToHaveAttributeAsync("aria-expanded", "false"); // Navigate into the Audit section via an in-page link (SPA navigation, // which raises NavigationManager.LocationChanged) — the Configuration // Audit Log quick-action card on the dashboard. await page.Locator("a[href='/audit/configuration']").First.ClickAsync(); await PlaywrightFixture.WaitForPathAsync(page, "/audit/configuration"); // The Audit nav section auto-expanded on arrival. await Expect(auditToggle).ToHaveAttributeAsync("aria-expanded", "true"); } private static ILocatorAssertions Expect(ILocator locator) => Assertions.Expect(locator); }