using Fluxor;
using GoodWood.Application.DTOs;
using GoodWood.Application.Interfaces;
using GoodWood.Domain.Interfaces;
using GoodWood.Web.Controllers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace GoodWood.Tests.Integration;
///
/// Integration tests for AuthController.
/// Tests controller logic without full HTTP pipeline.
///
public class AuthControllerTests
{
private readonly Mock _dispatcherMock;
private readonly Mock _userServiceMock;
private readonly Mock _emailServiceMock;
private readonly AuthController _sut;
public AuthControllerTests()
{
_dispatcherMock = new Mock();
_userServiceMock = new Mock();
_emailServiceMock = new Mock();
_sut = new AuthController(_dispatcherMock.Object, _userServiceMock.Object, _emailServiceMock.Object);
// Setup controller context with request info for password reset URL building
var httpContext = new DefaultHttpContext();
httpContext.Request.Scheme = "https";
httpContext.Request.Host = new HostString("localhost");
_sut.ControllerContext = new ControllerContext
{
HttpContext = httpContext
};
}
#region Login Tests
[Fact]
public async Task Login_ReturnsRedirectToHome_WhenCredentialsValid()
{
// Arrange
var loginDto = new LoginDto
{
Email = "test@example.com",
Password = "password123",
ReturnUrl = "/"
};
_userServiceMock.Setup(s => s.LoginAsync(It.IsAny(), It.IsAny()))
.ReturnsAsync(new UserDto { DisplayName = "Test User" });
// Act
var result = await _sut.Login(loginDto);
// Assert
result.Should().BeOfType();
var redirectResult = (LocalRedirectResult)result;
redirectResult.Url.Should().Be("/");
}
[Fact]
public async Task Login_ReturnsRedirectToLoginWithError_WhenCredentialsInvalid()
{
// Arrange
var loginDto = new LoginDto
{
Email = "invalid@example.com",
Password = "wrongpassword"
};
_userServiceMock.Setup(s => s.LoginAsync(It.IsAny(), It.IsAny()))
.ReturnsAsync((UserDto?)null);
// Act
var result = await _sut.Login(loginDto);
// Assert
result.Should().BeOfType();
var redirectResult = (LocalRedirectResult)result;
redirectResult.Url.Should().Contain("error=true");
}
[Fact]
public async Task Login_UsesDefaultReturnUrl_WhenNotProvided()
{
// Arrange
var loginDto = new LoginDto
{
Email = "test@example.com",
Password = "password123",
ReturnUrl = null
};
_userServiceMock.Setup(s => s.LoginAsync(It.IsAny(), It.IsAny()))
.ReturnsAsync(new UserDto { DisplayName = "Test User" });
// Act
var result = await _sut.Login(loginDto);
// Assert
result.Should().BeOfType();
var redirectResult = (LocalRedirectResult)result;
redirectResult.Url.Should().Be("/");
}
#endregion
#region Logout Tests
[Fact]
public async Task Logout_CallsSignOutAsync()
{
// Arrange
_userServiceMock.Setup(s => s.SignOutAsync())
.Returns(Task.CompletedTask);
// Act
await _sut.Logout();
// Assert
_userServiceMock.Verify(s => s.SignOutAsync(), Times.Once);
}
[Fact]
public async Task Logout_DispatchesLogoutCompleteAction()
{
// Arrange
_userServiceMock.Setup(s => s.SignOutAsync())
.Returns(Task.CompletedTask);
// Act
await _sut.Logout();
// Assert
_dispatcherMock.Verify(d => d.Dispatch(It.IsAny