using Microsoft.Playwright; namespace ScadaLink.CentralUI.PlaywrightTests; /// /// Verifies that navigation sections and links are shown/hidden based on the user's role. /// /// LDAP test users (all passwords: "password"): /// admin → Admin only /// designer → Design only /// deployer → Deployment only /// multi-role → Admin + Design + Deployment /// /// Nav structure (from NavMenu.razor): /// All authenticated: Dashboard, Monitoring (Health Dashboard, Event Logs, Parked Messages) /// Admin: LDAP Mappings, Sites, Data Connections, API Keys, Audit Log /// Design: Templates, Shared Scripts, External Systems, Areas /// Deployment: Instances, Deployments, Debug View /// [Collection("Playwright")] public class RoleNavigationTests { private readonly PlaywrightFixture _fixture; public RoleNavigationTests(PlaywrightFixture fixture) { _fixture = fixture; } // ── Admin-only user ───────────────────────────────────────────── [Fact] public async Task AdminUser_SeesAdminSection() { var page = await _fixture.NewAuthenticatedPageAsync("admin", "password"); await AssertNavLinkVisible(page, "Sites"); await AssertNavLinkVisible(page, "Data Connections"); await AssertNavLinkVisible(page, "API Keys"); await AssertNavLinkVisible(page, "LDAP Mappings"); await AssertNavLinkVisible(page, "Audit Log"); } [Fact] public async Task AdminUser_DoesNotSeeDesignSection() { var page = await _fixture.NewAuthenticatedPageAsync("admin", "password"); await AssertNavLinkHidden(page, "Templates"); await AssertNavLinkHidden(page, "Shared Scripts"); await AssertNavLinkHidden(page, "External Systems"); } [Fact] public async Task AdminUser_DoesNotSeeDeploymentSection() { var page = await _fixture.NewAuthenticatedPageAsync("admin", "password"); await AssertNavLinkHidden(page, "Instances"); await AssertNavLinkHidden(page, "Deployments"); await AssertNavLinkHidden(page, "Debug View"); } [Fact] public async Task AdminUser_SeesMonitoringSection() { var page = await _fixture.NewAuthenticatedPageAsync("admin", "password"); await AssertNavLinkVisible(page, "Health Dashboard"); await AssertNavLinkVisible(page, "Event Logs"); await AssertNavLinkVisible(page, "Parked Messages"); } // ── Design-only user ──────────────────────────────────────────── [Fact] public async Task DesignUser_SeesDesignSection() { var page = await _fixture.NewAuthenticatedPageAsync("designer", "password"); await AssertNavLinkVisible(page, "Templates"); await AssertNavLinkVisible(page, "Shared Scripts"); await AssertNavLinkVisible(page, "External Systems"); await AssertNavLinkVisible(page, "Areas"); } [Fact] public async Task DesignUser_DoesNotSeeAdminSection() { var page = await _fixture.NewAuthenticatedPageAsync("designer", "password"); await AssertNavLinkHidden(page, "Sites"); await AssertNavLinkHidden(page, "Data Connections"); await AssertNavLinkHidden(page, "API Keys"); await AssertNavLinkHidden(page, "LDAP Mappings"); await AssertNavLinkHidden(page, "Audit Log"); } [Fact] public async Task DesignUser_DoesNotSeeDeploymentSection() { var page = await _fixture.NewAuthenticatedPageAsync("designer", "password"); await AssertNavLinkHidden(page, "Instances"); await AssertNavLinkHidden(page, "Deployments"); await AssertNavLinkHidden(page, "Debug View"); } [Fact] public async Task DesignUser_SeesMonitoringButNotAuditLog() { var page = await _fixture.NewAuthenticatedPageAsync("designer", "password"); await AssertNavLinkVisible(page, "Health Dashboard"); await AssertNavLinkVisible(page, "Event Logs"); await AssertNavLinkVisible(page, "Parked Messages"); await AssertNavLinkHidden(page, "Audit Log"); } // ── Deployment-only user ──────────────────────────────────────── [Fact] public async Task DeploymentUser_SeesDeploymentSection() { var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password"); await AssertNavLinkVisible(page, "Instances"); await AssertNavLinkVisible(page, "Deployments"); await AssertNavLinkVisible(page, "Debug View"); } [Fact] public async Task DeploymentUser_DoesNotSeeAdminSection() { var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password"); await AssertNavLinkHidden(page, "Sites"); await AssertNavLinkHidden(page, "Data Connections"); await AssertNavLinkHidden(page, "API Keys"); await AssertNavLinkHidden(page, "LDAP Mappings"); await AssertNavLinkHidden(page, "Audit Log"); } [Fact] public async Task DeploymentUser_DoesNotSeeDesignSection() { var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password"); await AssertNavLinkHidden(page, "Templates"); await AssertNavLinkHidden(page, "Shared Scripts"); await AssertNavLinkHidden(page, "External Systems"); } [Fact] public async Task DeploymentUser_SeesMonitoringButNotAuditLog() { var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password"); await AssertNavLinkVisible(page, "Health Dashboard"); await AssertNavLinkVisible(page, "Event Logs"); await AssertNavLinkVisible(page, "Parked Messages"); await AssertNavLinkHidden(page, "Audit Log"); } // ── Multi-role user (Admin + Design + Deployment) ─────────────── [Fact] public async Task MultiRoleUser_SeesAllSections() { var page = await _fixture.NewAuthenticatedPageAsync("multi-role", "password"); // Admin await AssertNavLinkVisible(page, "Sites"); await AssertNavLinkVisible(page, "Data Connections"); await AssertNavLinkVisible(page, "API Keys"); await AssertNavLinkVisible(page, "LDAP Mappings"); await AssertNavLinkVisible(page, "Audit Log"); // Design await AssertNavLinkVisible(page, "Templates"); await AssertNavLinkVisible(page, "Shared Scripts"); await AssertNavLinkVisible(page, "External Systems"); await AssertNavLinkVisible(page, "Areas"); // Deployment await AssertNavLinkVisible(page, "Instances"); await AssertNavLinkVisible(page, "Deployments"); await AssertNavLinkVisible(page, "Debug View"); // Monitoring (all authenticated) await AssertNavLinkVisible(page, "Health Dashboard"); await AssertNavLinkVisible(page, "Event Logs"); await AssertNavLinkVisible(page, "Parked Messages"); } // ── All users see Dashboard ───────────────────────────────────── [Theory] [InlineData("admin")] [InlineData("designer")] [InlineData("deployer")] [InlineData("multi-role")] public async Task AllUsers_SeeDashboardLink(string username) { var page = await _fixture.NewAuthenticatedPageAsync(username, "password"); var dashboardLink = page.GetByRole(AriaRole.Link, new() { Name = "Dashboard", Exact = true }); await Assertions.Expect(dashboardLink).ToBeVisibleAsync(); } // ── Helpers ───────────────────────────────────────────────────── private static async Task AssertNavLinkVisible(IPage page, string linkText) { var locator = page.Locator($"nav a:has-text('{linkText}')"); var count = await locator.CountAsync(); Assert.True(count > 0, $"Expected nav link '{linkText}' to be visible, but it was not found"); } private static async Task AssertNavLinkHidden(IPage page, string linkText) { var locator = page.Locator($"nav a:has-text('{linkText}')"); var count = await locator.CountAsync(); Assert.True(count == 0, $"Expected nav link '{linkText}' to be hidden, but it was found"); } }