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);
}
}