Files
pos-system/microservices/apps/web-client-tpos-net/tests/WebClientTpos.ComponentTests/Services/AuthStateServiceTests.cs
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

203 lines
5.4 KiB
C#

using FluentAssertions;
using WebClientTpos.Client.Services;
using Xunit;
namespace WebClientTpos.ComponentTests.Services;
/// <summary>
/// EN: Unit tests for AuthStateService — singleton tracking auth state in the POS app.
/// Token is managed by BFF httpOnly cookie; this service only tracks email, role, expiry.
/// VI: Unit tests cho AuthStateService — singleton theo dõi trạng thái auth trong POS app.
/// Token được quản lý bởi BFF httpOnly cookie; service này chỉ lưu email, role, expiry.
/// </summary>
public class AuthStateServiceTests
{
private static AuthStateService CreateSut() => new();
// -----------------------------------------------------------------------
// Initial state
// -----------------------------------------------------------------------
[Fact]
public void InitialState_ShouldNotBeAuthenticated()
{
// Arrange & Act
var sut = CreateSut();
// Assert
sut.IsAuthenticated.Should().BeFalse();
sut.UserEmail.Should().BeNull();
sut.UserRole.Should().BeNull();
sut.TokenExpiry.Should().BeNull();
}
// -----------------------------------------------------------------------
// Login
// -----------------------------------------------------------------------
[Fact]
public void Login_WithValidCredentials_ShouldSetAuthenticatedState()
{
// Arrange
var sut = CreateSut();
// Act
sut.Login("owner@goodgo.vn", "owner");
// Assert
sut.IsAuthenticated.Should().BeTrue();
sut.UserEmail.Should().Be("owner@goodgo.vn");
sut.UserRole.Should().Be("owner");
}
[Theory]
[InlineData("owner")]
[InlineData("staff")]
[InlineData("customer")]
[InlineData("branch")]
public void Login_WithAnyRole_ShouldSetRole(string role)
{
// Arrange
var sut = CreateSut();
// Act
sut.Login("user@goodgo.vn", role);
// Assert
sut.UserRole.Should().Be(role);
}
[Fact]
public void Login_CalledTwiceWithSameData_ShouldNotFireOnChange()
{
// Arrange
var sut = CreateSut();
sut.Login("user@goodgo.vn", "owner");
var changeCount = 0;
sut.OnChange += () => changeCount++;
// Act — same email + same role again
sut.Login("user@goodgo.vn", "owner");
// Assert
// EN: Idempotent login must not trigger OnChange / VI: Login idempotent không kích hoạt OnChange
changeCount.Should().Be(0);
}
[Fact]
public void Login_WithNewRole_ShouldFireOnChange()
{
// Arrange
var sut = CreateSut();
sut.Login("user@goodgo.vn", "staff");
var changeCount = 0;
sut.OnChange += () => changeCount++;
// Act
sut.Login("user@goodgo.vn", "owner");
// Assert
changeCount.Should().BeGreaterThan(0);
}
// -----------------------------------------------------------------------
// Logout
// -----------------------------------------------------------------------
[Fact]
public void Logout_AfterLogin_ShouldClearState()
{
// Arrange
var sut = CreateSut();
sut.Login("owner@goodgo.vn", "owner");
// Act
sut.Logout();
// Assert
sut.IsAuthenticated.Should().BeFalse();
sut.UserEmail.Should().BeNull();
sut.UserRole.Should().BeNull();
}
[Fact]
public void Logout_ShouldFireOnChange()
{
// Arrange
var sut = CreateSut();
sut.Login("user@goodgo.vn", "staff");
var fired = false;
sut.OnChange += () => fired = true;
// Act
sut.Logout();
// Assert
fired.Should().BeTrue();
}
// -----------------------------------------------------------------------
// GetPortalUrl
// -----------------------------------------------------------------------
[Theory]
[InlineData("owner", "/admin")]
[InlineData("admin", "/admin")]
[InlineData("staff", "/staff/dashboard")]
[InlineData("branch", "/admin")]
[InlineData("customer", "/app")]
[InlineData("unknown", "/auth/login")]
[InlineData(null, "/auth/login")]
public void GetPortalUrl_ShouldReturnCorrectPathForRole(string? role, string expectedUrl)
{
// Arrange
var sut = CreateSut();
if (role != null)
{
sut.Login("user@goodgo.vn", role);
}
// Act
var url = sut.GetPortalUrl();
// Assert
url.Should().Be(expectedUrl);
}
// -----------------------------------------------------------------------
// OnChange event
// -----------------------------------------------------------------------
[Fact]
public void OnChange_ShouldBeRaisedOnLogin()
{
// Arrange
var sut = CreateSut();
var raised = false;
sut.OnChange += () => raised = true;
// Act
sut.Login("new@goodgo.vn", "owner");
// Assert
raised.Should().BeTrue();
}
[Fact]
public void OnChange_MultipleSubscribers_ShouldAllBeNotified()
{
// Arrange
var sut = CreateSut();
var count = 0;
sut.OnChange += () => count++;
sut.OnChange += () => count++;
sut.OnChange += () => count++;
// Act
sut.Logout();
// Assert
count.Should().Be(3);
}
}