198 lines
6.7 KiB
C#
198 lines
6.7 KiB
C#
using Bunit;
|
|
using Bunit.TestDoubles;
|
|
using Fluxor;
|
|
using Koogle.Application.DTOs;
|
|
using Koogle.Application.Interfaces;
|
|
using Koogle.Web.Store.AuthState;
|
|
using Koogle.Web.Store.ClubState;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using MudBlazor;
|
|
using MudBlazor.Services;
|
|
using System.Security.Claims;
|
|
|
|
namespace Koogle.Tests.Components;
|
|
|
|
/// <summary>
|
|
/// Tests for the Home page component.
|
|
/// </summary>
|
|
public class HomePageTests : IDisposable
|
|
{
|
|
private readonly TestContext _ctx;
|
|
private readonly Mock<IUserService> _userServiceMock;
|
|
private readonly Mock<ICurrentClubContext> _clubContextMock;
|
|
private readonly Mock<IDispatcher> _dispatcherMock;
|
|
private readonly Mock<IState<AuthState>> _authStateMock;
|
|
private readonly Mock<IState<ClubState>> _clubStateMock;
|
|
private readonly Mock<IAuthorizationService> _authorizationServiceMock;
|
|
|
|
public HomePageTests()
|
|
{
|
|
_ctx = new TestContext();
|
|
_userServiceMock = new Mock<IUserService>();
|
|
_clubContextMock = new Mock<ICurrentClubContext>();
|
|
_dispatcherMock = new Mock<IDispatcher>();
|
|
|
|
// Setup default club context
|
|
_clubContextMock.Setup(c => c.ClubId).Returns(Guid.NewGuid());
|
|
_clubContextMock.Setup(c => c.ClubName).Returns("Test Club");
|
|
|
|
// Setup Fluxor states - required by Home page and child components
|
|
_authStateMock = new Mock<IState<AuthState>>();
|
|
_authStateMock.Setup(s => s.Value).Returns(AuthState.Initial);
|
|
|
|
_clubStateMock = new Mock<IState<ClubState>>();
|
|
_clubStateMock.Setup(s => s.Value).Returns(ClubState.Initial);
|
|
|
|
// Setup authorization service mock
|
|
_authorizationServiceMock = new Mock<IAuthorizationService>();
|
|
_authorizationServiceMock
|
|
.Setup(s => s.AuthorizeAsync(
|
|
It.IsAny<ClaimsPrincipal>(),
|
|
It.IsAny<object?>(),
|
|
It.IsAny<string>()))
|
|
.ReturnsAsync(AuthorizationResult.Success());
|
|
|
|
// Register all services before any rendering
|
|
_ctx.Services.AddMudServices(options =>
|
|
{
|
|
options.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight;
|
|
});
|
|
|
|
_ctx.Services.AddSingleton(_userServiceMock.Object);
|
|
_ctx.Services.AddSingleton(_clubContextMock.Object);
|
|
_ctx.Services.AddSingleton(_dispatcherMock.Object);
|
|
_ctx.Services.AddSingleton(_authStateMock.Object);
|
|
_ctx.Services.AddSingleton(_clubStateMock.Object);
|
|
_ctx.Services.AddSingleton(_authorizationServiceMock.Object);
|
|
|
|
// Additional Fluxor services required by components
|
|
_ctx.Services.AddSingleton(new Mock<IActionSubscriber>().Object);
|
|
_ctx.Services.AddSingleton(new Mock<IStore>().Object);
|
|
|
|
// ASP.NET Core services needed by child components
|
|
var httpContextAccessorMock = new Mock<IHttpContextAccessor>();
|
|
httpContextAccessorMock.Setup(x => x.HttpContext).Returns(new DefaultHttpContext());
|
|
_ctx.Services.AddSingleton(httpContextAccessorMock.Object);
|
|
|
|
// Stub complex components to avoid deep dependency chains
|
|
_ctx.ComponentFactories.AddStub<Koogle.Web.Components.Shared.LogoutButton>();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_ctx.Dispose();
|
|
}
|
|
|
|
[Fact]
|
|
public void HomePage_RendersWelcomeMessage_WhenAuthorized()
|
|
{
|
|
// Arrange
|
|
var authContext = _ctx.AddTestAuthorization();
|
|
authContext.SetAuthorized("testuser");
|
|
|
|
// Setup authenticated auth state
|
|
_authStateMock.Setup(s => s.Value).Returns(CreateAuthState());
|
|
|
|
// Act
|
|
var cut = _ctx.RenderComponent<Koogle.Web.Components.Pages.Home>();
|
|
|
|
// Assert
|
|
cut.Markup.Should().Contain("Hello, world!");
|
|
cut.Markup.Should().Contain("Welcome to your new app");
|
|
}
|
|
|
|
[Fact]
|
|
public void HomePage_SetsPageTitle()
|
|
{
|
|
// Arrange
|
|
var authContext = _ctx.AddTestAuthorization();
|
|
authContext.SetAuthorized("testuser");
|
|
|
|
// Setup authenticated auth state
|
|
_authStateMock.Setup(s => s.Value).Returns(CreateAuthState());
|
|
|
|
// Act
|
|
var cut = _ctx.RenderComponent<Koogle.Web.Components.Pages.Home>();
|
|
|
|
// Assert
|
|
var pageTitle = cut.FindComponent<Microsoft.AspNetCore.Components.Web.PageTitle>();
|
|
pageTitle.Should().NotBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void HomePage_DisplaysCurrentClub_WhenAuthorized()
|
|
{
|
|
// Arrange
|
|
var authContext = _ctx.AddTestAuthorization();
|
|
authContext.SetAuthorized("testuser");
|
|
|
|
_authStateMock.Setup(s => s.Value).Returns(CreateAuthState());
|
|
_clubContextMock.Setup(c => c.ClubName).Returns("Kegel Freunde 2025");
|
|
|
|
// Act
|
|
var cut = _ctx.RenderComponent<Koogle.Web.Components.Pages.Home>();
|
|
|
|
// Assert - AuthTest component shows current club name
|
|
cut.Markup.Should().Contain("Kegel Freunde 2025");
|
|
}
|
|
|
|
[Fact]
|
|
public void HomePage_ShowsUserDisplayName_WhenAuthenticated()
|
|
{
|
|
// Arrange
|
|
var authContext = _ctx.AddTestAuthorization();
|
|
authContext.SetAuthorized("testuser");
|
|
|
|
var authState = CreateAuthState("Max Mustermann");
|
|
_authStateMock.Setup(s => s.Value).Returns(authState);
|
|
|
|
// Act
|
|
var cut = _ctx.RenderComponent<Koogle.Web.Components.Pages.Home>();
|
|
|
|
// Assert - AuthTest component shows user display name
|
|
cut.Markup.Should().Contain("Max Mustermann");
|
|
}
|
|
|
|
[Fact]
|
|
public void HomePage_ShowsAuthTestComponent()
|
|
{
|
|
// Arrange
|
|
var authContext = _ctx.AddTestAuthorization();
|
|
authContext.SetAuthorized("testuser");
|
|
|
|
_authStateMock.Setup(s => s.Value).Returns(CreateAuthState());
|
|
|
|
// Act
|
|
var cut = _ctx.RenderComponent<Koogle.Web.Components.Pages.Home>();
|
|
|
|
// Assert - AuthTest component header is rendered
|
|
cut.Markup.Should().Contain("AuthTest-Component");
|
|
}
|
|
|
|
private static AuthState CreateAuthState(string displayName = "Test User")
|
|
{
|
|
return AuthState.Initial with
|
|
{
|
|
IsAuthenticated = true,
|
|
IsLoading = false,
|
|
CurrentUser = new UserDto
|
|
{
|
|
ProfileId = Guid.NewGuid(),
|
|
IdentityUserId = Guid.NewGuid(),
|
|
DisplayName = displayName,
|
|
Identity = new ApplicationUserDto
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Email = "test@example.com",
|
|
UserName = "test@example.com"
|
|
}
|
|
},
|
|
Roles = [],
|
|
Error = null
|
|
};
|
|
}
|
|
}
|