using System.Security.Claims; using Microsoft.AspNetCore.Components.Authorization; using ScadaLink.CentralUI.Auth; using ScadaLink.Security; namespace ScadaLink.CentralUI.Tests.Auth; /// /// Regression tests for CentralUI-024. Ten components each copy-pasted a /// GetCurrentUserAsync helper using the magic string /// FindFirst("Username"), and NavMenu/Dashboard used /// FindFirst("DisplayName"). A rename of the claim type in /// (the single source of truth) would have /// silently broken every call site. The shared /// helpers now resolve the claim type /// through the JwtTokenService constants. /// public class ClaimsPrincipalExtensionsTests { private static ClaimsPrincipal Principal(params Claim[] claims) => new(new ClaimsIdentity(claims, authenticationType: "TestCookie")); [Fact] public void GetUsername_ResolvesTheJwtTokenServiceUsernameClaim() { var principal = Principal( new Claim(JwtTokenService.UsernameClaimType, "alice")); Assert.Equal("alice", principal.GetUsername()); } [Fact] public void GetUsername_FallsBackToUnknown_WhenClaimAbsent() { var principal = Principal(); Assert.Equal(ClaimsPrincipalExtensions.UnknownUser, principal.GetUsername()); } [Fact] public void GetDisplayName_ResolvesTheJwtTokenServiceDisplayNameClaim() { var principal = Principal( new Claim(JwtTokenService.DisplayNameClaimType, "Alice Anderson")); Assert.Equal("Alice Anderson", principal.GetDisplayName()); } [Fact] public void GetDisplayName_IsNull_WhenClaimAbsent() { Assert.Null(Principal().GetDisplayName()); } [Fact] public async Task GetCurrentUsernameAsync_ReadsUsernameFromAuthState() { var principal = Principal( new Claim(JwtTokenService.UsernameClaimType, "bob")); var provider = new StubAuthStateProvider( new AuthenticationState(principal)); Assert.Equal("bob", await provider.GetCurrentUsernameAsync()); } [Fact] public void Username_LookupTracksAJwtTokenServiceRename() { // The lookup must NOT use a hard-coded "Username" literal: if the // constant's *value* is ever changed, the helper must follow it. Build a // principal whose claim carries the JwtTokenService constant's current // value and confirm the helper finds it via that same constant. var principal = Principal( new Claim(JwtTokenService.UsernameClaimType, "carol")); Assert.Equal("carol", principal.FindFirst(JwtTokenService.UsernameClaimType)?.Value); Assert.Equal("carol", principal.GetUsername()); } private sealed class StubAuthStateProvider : AuthenticationStateProvider { private readonly AuthenticationState _state; public StubAuthStateProvider(AuthenticationState state) => _state = state; public override Task GetAuthenticationStateAsync() => Task.FromResult(_state); } }