refactor: replace FakeChatService with FakeUserService for user authentication and profile handling in tests

This commit is contained in:
HueByte
2026-02-23 15:52:18 +01:00
parent 6e76065dcb
commit 94b31b6056
2 changed files with 51 additions and 17 deletions
@@ -12,11 +12,12 @@ public class IrcCommandHandlerTests
{ {
private readonly IrcOptions _options = new() { ServerName = "testserver", Motd = null }; private readonly IrcOptions _options = new() { ServerName = "testserver", Motd = null };
private readonly FakeChatService _chatService = new(); private readonly FakeChatService _chatService = new();
private readonly FakeUserService _userService = new();
private readonly FakeChannelService _channelService = new(); private readonly FakeChannelService _channelService = new();
private readonly FakeEncryptionService _encryption = new(); private readonly FakeEncryptionService _encryption = new();
private IrcCommandHandler CreateHandler(IrcClientConnection conn) => private IrcCommandHandler CreateHandler(IrcClientConnection conn) =>
new(conn, _options, _chatService, _channelService, _encryption, NullLogger.Instance); new(conn, _options, _chatService, _userService, _channelService, _encryption, NullLogger.Instance);
private async Task<List<string>> RunAndCapture(string[] inputLines, private async Task<List<string>> RunAndCapture(string[] inputLines,
Action<IrcClientConnection>? setup = null) Action<IrcClientConnection>? setup = null)
@@ -85,7 +86,7 @@ public class IrcCommandHandlerTests
public async Task PassNickUser_ValidCredentials_Registers() public async Task PassNickUser_ValidCredentials_Registers()
{ {
var userId = Guid.NewGuid(); var userId = Guid.NewGuid();
_chatService.AuthResult = (userId, "alice"); _userService.AuthResult = FakeUserService.SuccessResult(userId, "alice");
var lines = await RunAndCapture([ var lines = await RunAndCapture([
"PASS secret123", "PASS secret123",
@@ -112,7 +113,7 @@ public class IrcCommandHandlerTests
[Fact] [Fact]
public async Task PassNickUser_WrongPassword_GetsAuthError() public async Task PassNickUser_WrongPassword_GetsAuthError()
{ {
_chatService.AuthResult = null; _userService.AuthResult = null;
var lines = await RunAndCapture([ var lines = await RunAndCapture([
"PASS wrongpassword", "PASS wrongpassword",
@@ -120,7 +121,8 @@ public class IrcCommandHandlerTests
"USER alice 0 * :Alice Smith" "USER alice 0 * :Alice Smith"
]); ]);
Assert.Contains(lines, l => l.Contains("464") && l.Contains("incorrect")); Assert.Contains(lines, l => l.Contains("464"));
Assert.Contains(lines, l => l.Contains("ERROR") && l.Contains("Authentication failed"));
} }
[Fact] [Fact]
@@ -189,7 +191,7 @@ public class IrcCommandHandlerTests
public async Task SaslPlain_ValidCredentials_Authenticates() public async Task SaslPlain_ValidCredentials_Authenticates()
{ {
var userId = Guid.NewGuid(); var userId = Guid.NewGuid();
_chatService.AuthResult = (userId, "alice"); _userService.AuthResult = FakeUserService.SuccessResult(userId, "alice");
var saslPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes("\0alice\0password123")); var saslPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes("\0alice\0password123"));
@@ -210,7 +212,7 @@ public class IrcCommandHandlerTests
[Fact] [Fact]
public async Task SaslPlain_InvalidCredentials_GetsError() public async Task SaslPlain_InvalidCredentials_GetsError()
{ {
_chatService.AuthResult = null; _userService.AuthResult = null;
var saslPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes("\0alice\0wrongpwd")); var saslPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes("\0alice\0wrongpwd"));
@@ -478,7 +480,7 @@ public class IrcCommandHandlerTests
[Fact] [Fact]
public async Task Whois_ExistingUser_ReturnsInfo() public async Task Whois_ExistingUser_ReturnsInfo()
{ {
_chatService.ProfileToReturn = new UserProfileDto( _userService.ProfileToReturn = new UserProfileDto(
Guid.NewGuid(), "bob", "Bob S.", "Hello!", null, null, Guid.NewGuid(), "bob", "Bob S.", "Hello!", null, null,
UserStatus.Online, null, ServerRole.Member, UserStatus.Online, null, ServerRole.Member,
DateTimeOffset.UtcNow.AddDays(-30), DateTimeOffset.UtcNow); DateTimeOffset.UtcNow.AddDays(-30), DateTimeOffset.UtcNow);
@@ -496,7 +498,7 @@ public class IrcCommandHandlerTests
[Fact] [Fact]
public async Task Whois_NonexistentUser_GetsNoSuchNickError() public async Task Whois_NonexistentUser_GetsNoSuchNickError()
{ {
_chatService.ProfileToReturn = null; _userService.ProfileToReturn = null;
var lines = await RunAuthenticated(["WHOIS ghost"]); var lines = await RunAuthenticated(["WHOIS ghost"]);
@@ -506,7 +508,7 @@ public class IrcCommandHandlerTests
[Fact] [Fact]
public async Task Whois_AwayUser_ShowsAwayMessage() public async Task Whois_AwayUser_ShowsAwayMessage()
{ {
_chatService.ProfileToReturn = new UserProfileDto( _userService.ProfileToReturn = new UserProfileDto(
Guid.NewGuid(), "bob", null, null, null, null, Guid.NewGuid(), "bob", null, null, null, null,
UserStatus.Away, "Gone fishing", ServerRole.Member, UserStatus.Away, "Gone fishing", ServerRole.Member,
DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow); DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow);
+40 -8
View File
@@ -156,8 +156,6 @@ internal sealed class FakeChatService : IChatService
public List<MessageDto> HistoryToReturn { get; set; } = []; public List<MessageDto> HistoryToReturn { get; set; } = [];
public string? JoinError { get; set; } public string? JoinError { get; set; }
public string? SendMessageError { get; set; } public string? SendMessageError { get; set; }
public (Guid UserId, string Username)? AuthResult { get; set; }
public UserProfileDto? ProfileToReturn { get; set; }
public List<string> ChannelsForUserToReturn { get; set; } = []; public List<string> ChannelsForUserToReturn { get; set; } = [];
public List<UserPresenceDto> OnlineUsersToReturn { get; set; } = []; public List<UserPresenceDto> OnlineUsersToReturn { get; set; } = [];
@@ -210,14 +208,8 @@ internal sealed class FakeChatService : IChatService
public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null) => public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null) =>
Task.CompletedTask; Task.CompletedTask;
public Task<UserProfileDto?> GetUserProfileAsync(string username) =>
Task.FromResult(ProfileToReturn);
public Task<List<string>> GetChannelsForUserAsync(string username) => public Task<List<string>> GetChannelsForUserAsync(string username) =>
Task.FromResult(ChannelsForUserToReturn); Task.FromResult(ChannelsForUserToReturn);
public Task<(Guid UserId, string Username)?> AuthenticateUserAsync(string username, string password) =>
Task.FromResult(AuthResult);
} }
/// <summary> /// <summary>
@@ -258,3 +250,43 @@ internal sealed class FakeChannelService : IChannelService
public Task<(bool Success, string? Error)> EnsureChannelMembershipAsync(Guid userId, string channelName) => public Task<(bool Success, string? Error)> EnsureChannelMembershipAsync(Guid userId, string channelName) =>
Task.FromResult(MembershipResult); Task.FromResult(MembershipResult);
} }
/// <summary>
/// Fake user service that records method calls and returns pre-configured results.
/// </summary>
internal sealed class FakeUserService : IUserService
{
// Configurable results
public UserOperationResult? AuthResult { get; set; }
public UserOperationResult? RegisterResult { get; set; }
public UserProfileDto? ProfileToReturn { get; set; }
/// <summary>
/// Helper to create a success result from a simple userId + username pair.
/// </summary>
public static UserOperationResult SuccessResult(Guid userId, string username) =>
UserOperationResult.Success(new UserProfileDto(
userId, username, null, null, null, null,
UserStatus.Online, null, ServerRole.Member,
DateTimeOffset.UtcNow, DateTimeOffset.UtcNow));
public Task<UserOperationResult> AuthenticateUserAsync(string username, string password) =>
Task.FromResult(AuthResult
?? UserOperationResult.Fail(UserError.InvalidCredentials, "Invalid username or password."));
public Task<UserOperationResult> RegisterUserAsync(string username, string password, string? displayName = null) =>
Task.FromResult(RegisterResult
?? UserOperationResult.Fail(UserError.AlreadyExists, "Username is already taken."));
public Task<UserProfileDto?> GetUserProfileAsync(string username) =>
Task.FromResult(ProfileToReturn);
public Task<UserProfileDto?> GetUserByIdAsync(Guid userId) =>
Task.FromResult(ProfileToReturn);
public Task<UserOperationResult> UpdateProfileAsync(Guid userId, string? displayName, string? bio, string? nicknameColor) =>
Task.FromResult(UserOperationResult.Fail(UserError.NotFound, "Not configured"));
public Task<UserOperationResult> SetAvatarAsync(Guid userId, string asciiArt) =>
Task.FromResult(UserOperationResult.Fail(UserError.NotFound, "Not configured"));
}