mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-04 08:36:11 +02:00
refactor: replace FakeChatService with FakeUserService for user authentication and profile handling in tests
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user