using Apps72.Dev.Data.DbMocker; using FluentAssertions; using Infrastructure.Repository.Auth; using Infrastructure.Repository.Tests.Database; namespace Infrastructure.Repository.Tests.Auth; public class AuthRepositoryTest { private static AuthRepository CreateRepo(MockDbConnection conn) => new(new TestConnectionFactory(conn)); [Fact] public async Task RegisterUserAsync_CreatesUserWithCredential_ReturnsUserAccount() { var expectedUserId = Guid.NewGuid(); var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "USP_RegisterUser") .ReturnsScalar(expectedUserId); // Mock the subsequent read for the newly created user by id conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountById") .ReturnsTable( MockTable .WithColumns( ("UserAccountId", typeof(Guid)), ("Username", typeof(string)), ("FirstName", typeof(string)), ("LastName", typeof(string)), ("Email", typeof(string)), ("CreatedAt", typeof(DateTime)), ("UpdatedAt", typeof(DateTime?)), ("DateOfBirth", typeof(DateTime)), ("Timer", typeof(byte[])) ) .AddRow( expectedUserId, "testuser", "Test", "User", "test@example.com", DateTime.UtcNow, null, new DateTime(1990, 1, 1), null ) ); var repo = CreateRepo(conn); var result = await repo.RegisterUserAsync( username: "testuser", firstName: "Test", lastName: "User", email: "test@example.com", dateOfBirth: new DateTime(1990, 1, 1), passwordHash: "hashedpassword123" ); result.Should().NotBeNull(); result.UserAccountId.Should().Be(expectedUserId); result.Username.Should().Be("testuser"); result.FirstName.Should().Be("Test"); result.LastName.Should().Be("User"); result.Email.Should().Be("test@example.com"); result.DateOfBirth.Should().Be(new DateTime(1990, 1, 1)); } [Fact] public async Task GetUserByEmailAsync_ReturnsUser_WhenExists() { var userId = Guid.NewGuid(); var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByEmail") .ReturnsTable( MockTable .WithColumns( ("UserAccountId", typeof(Guid)), ("Username", typeof(string)), ("FirstName", typeof(string)), ("LastName", typeof(string)), ("Email", typeof(string)), ("CreatedAt", typeof(DateTime)), ("UpdatedAt", typeof(DateTime?)), ("DateOfBirth", typeof(DateTime)), ("Timer", typeof(byte[])) ) .AddRow( userId, "emailuser", "Email", "User", "emailuser@example.com", DateTime.UtcNow, null, new DateTime(1990, 5, 15), null ) ); var repo = CreateRepo(conn); var result = await repo.GetUserByEmailAsync("emailuser@example.com"); result.Should().NotBeNull(); result!.UserAccountId.Should().Be(userId); result.Username.Should().Be("emailuser"); result.Email.Should().Be("emailuser@example.com"); result.FirstName.Should().Be("Email"); result.LastName.Should().Be("User"); } [Fact] public async Task GetUserByEmailAsync_ReturnsNull_WhenNotExists() { var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByEmail") .ReturnsTable(MockTable.Empty()); var repo = CreateRepo(conn); var result = await repo.GetUserByEmailAsync("nonexistent@example.com"); result.Should().BeNull(); } [Fact] public async Task GetUserByUsernameAsync_ReturnsUser_WhenExists() { var userId = Guid.NewGuid(); var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByUsername" ) .ReturnsTable( MockTable .WithColumns( ("UserAccountId", typeof(Guid)), ("Username", typeof(string)), ("FirstName", typeof(string)), ("LastName", typeof(string)), ("Email", typeof(string)), ("CreatedAt", typeof(DateTime)), ("UpdatedAt", typeof(DateTime?)), ("DateOfBirth", typeof(DateTime)), ("Timer", typeof(byte[])) ) .AddRow( userId, "usernameuser", "Username", "User", "username@example.com", DateTime.UtcNow, null, new DateTime(1985, 8, 20), null ) ); var repo = CreateRepo(conn); var result = await repo.GetUserByUsernameAsync("usernameuser"); result.Should().NotBeNull(); result!.UserAccountId.Should().Be(userId); result.Username.Should().Be("usernameuser"); result.Email.Should().Be("username@example.com"); } [Fact] public async Task GetUserByUsernameAsync_ReturnsNull_WhenNotExists() { var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByUsername" ) .ReturnsTable(MockTable.Empty()); var repo = CreateRepo(conn); var result = await repo.GetUserByUsernameAsync("nonexistent"); result.Should().BeNull(); } [Fact] public async Task GetActiveCredentialByUserAccountIdAsync_ReturnsCredential_WhenExists() { var userId = Guid.NewGuid(); var credentialId = Guid.NewGuid(); var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "USP_GetActiveUserCredentialByUserAccountId" ) .ReturnsTable( MockTable .WithColumns( ("UserCredentialId", typeof(Guid)), ("UserAccountId", typeof(Guid)), ("Hash", typeof(string)), ("CreatedAt", typeof(DateTime)), ("Timer", typeof(byte[])) ) .AddRow( credentialId, userId, "hashed_password_value", DateTime.UtcNow, null ) ); var repo = CreateRepo(conn); var result = await repo.GetActiveCredentialByUserAccountIdAsync(userId); result.Should().NotBeNull(); result!.UserCredentialId.Should().Be(credentialId); result.UserAccountId.Should().Be(userId); result.Hash.Should().Be("hashed_password_value"); } [Fact] public async Task GetActiveCredentialByUserAccountIdAsync_ReturnsNull_WhenNotExists() { var userId = Guid.NewGuid(); var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "USP_GetActiveUserCredentialByUserAccountId" ) .ReturnsTable(MockTable.Empty()); var repo = CreateRepo(conn); var result = await repo.GetActiveCredentialByUserAccountIdAsync(userId); result.Should().BeNull(); } [Fact] public async Task RotateCredentialAsync_ExecutesSuccessfully() { var userId = Guid.NewGuid(); var newPasswordHash = "new_hashed_password"; var conn = new MockDbConnection(); conn.Mocks.When(cmd => cmd.CommandText == "USP_RotateUserCredential") .ReturnsScalar(1); var repo = CreateRepo(conn); // Should not throw var act = async () => await repo.RotateCredentialAsync(userId, newPasswordHash); await act.Should().NotThrowAsync(); } }