- Add .NET 8 backend with Clean Architecture - Add React + Vite + TypeScript frontend - Implement authentication with JWT - Implement Azure Blob Storage client - Implement OCR integration - Implement supplier matching service - Implement voucher generation - Implement Fortnox provider - Add unit and integration tests - Add Docker Compose configuration
139 lines
4.9 KiB
C#
139 lines
4.9 KiB
C#
using InvoiceMaster.Application.Services;
|
|
using InvoiceMaster.Core.Entities;
|
|
using InvoiceMaster.Core.Interfaces;
|
|
using Moq;
|
|
using Xunit;
|
|
using FluentAssertions;
|
|
|
|
namespace InvoiceMaster.UnitTests.Services;
|
|
|
|
public class AuthServiceTests
|
|
{
|
|
private readonly Mock<IRepository<User>> _userRepositoryMock;
|
|
private readonly Mock<IUnitOfWork> _unitOfWorkMock;
|
|
private readonly AuthService _authService;
|
|
|
|
public AuthServiceTests()
|
|
{
|
|
_userRepositoryMock = new Mock<IRepository<User>>();
|
|
_unitOfWorkMock = new Mock<IUnitOfWork>();
|
|
|
|
var configuration = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
|
|
.AddInMemoryCollection(new Dictionary<string, string>
|
|
{
|
|
["Jwt:SecretKey"] = "this-is-a-test-secret-key-that-is-32-chars-long",
|
|
["Jwt:Issuer"] = "TestIssuer",
|
|
["Jwt:Audience"] = "TestAudience",
|
|
["Jwt:AccessTokenExpirationMinutes"] = "15",
|
|
["Jwt:RefreshTokenExpirationDays"] = "7"
|
|
})
|
|
.Build();
|
|
|
|
_authService = new AuthService(
|
|
_userRepositoryMock.Object,
|
|
_unitOfWorkMock.Object,
|
|
configuration);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RegisterAsync_WithNewEmail_ShouldCreateUser()
|
|
{
|
|
var users = new List<User>();
|
|
_userRepositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(users);
|
|
_userRepositoryMock.Setup(x => x.AddAsync(It.IsAny<User>(), It.IsAny<CancellationToken>()))
|
|
.Callback<User, CancellationToken>((u, _) => users.Add(u))
|
|
.ReturnsAsync((User u, CancellationToken _) => u);
|
|
_unitOfWorkMock.Setup(x => x.SaveChangesAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(1);
|
|
|
|
var result = await _authService.RegisterAsync(
|
|
new Application.Commands.Auth.RegisterCommand(
|
|
"test@example.com",
|
|
"Password123!",
|
|
"Test User"));
|
|
|
|
result.Success.Should().BeTrue();
|
|
result.User.Should().NotBeNull();
|
|
result.User!.Email.Should().Be("test@example.com");
|
|
result.Tokens.Should().NotBeNull();
|
|
result.Tokens!.AccessToken.Should().NotBeNullOrEmpty();
|
|
result.Tokens.RefreshToken.Should().NotBeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RegisterAsync_WithExistingEmail_ShouldReturnError()
|
|
{
|
|
var existingUser = new User
|
|
{
|
|
Email = "test@example.com",
|
|
HashedPassword = "hashed"
|
|
};
|
|
_userRepositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new List<User> { existingUser });
|
|
|
|
var result = await _authService.RegisterAsync(
|
|
new Application.Commands.Auth.RegisterCommand(
|
|
"test@example.com",
|
|
"Password123!",
|
|
"Test User"));
|
|
|
|
result.Success.Should().BeFalse();
|
|
result.ErrorMessage.Should().Be("Email already registered");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoginAsync_WithValidCredentials_ShouldReturnTokens()
|
|
{
|
|
var hashedPassword = ComputeHash("Password123!");
|
|
var user = new User
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Email = "test@example.com",
|
|
HashedPassword = hashedPassword,
|
|
IsActive = true
|
|
};
|
|
_userRepositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new List<User> { user });
|
|
_unitOfWorkMock.Setup(x => x.SaveChangesAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(1);
|
|
|
|
var result = await _authService.LoginAsync(
|
|
new Application.Commands.Auth.LoginCommand(
|
|
"test@example.com",
|
|
"Password123!"));
|
|
|
|
result.Success.Should().BeTrue();
|
|
result.User.Should().NotBeNull();
|
|
result.Tokens.Should().NotBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoginAsync_WithInvalidPassword_ShouldReturnError()
|
|
{
|
|
var user = new User
|
|
{
|
|
Email = "test@example.com",
|
|
HashedPassword = ComputeHash("CorrectPassword"),
|
|
IsActive = true
|
|
};
|
|
_userRepositoryMock.Setup(x => x.GetAllAsync(It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new List<User> { user });
|
|
|
|
var result = await _authService.LoginAsync(
|
|
new Application.Commands.Auth.LoginCommand(
|
|
"test@example.com",
|
|
"WrongPassword"));
|
|
|
|
result.Success.Should().BeFalse();
|
|
result.ErrorMessage.Should().Be("Invalid email or password");
|
|
}
|
|
|
|
private static string ComputeHash(string password)
|
|
{
|
|
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
|
var hashedBytes = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
|
|
return Convert.ToBase64String(hashedBytes);
|
|
}
|
|
}
|