203 lines
5.4 KiB
C#
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);
|
|
}
|
|
}
|