From 073d704ce6b12f4bd63d8c84d6219e2c917b41b3 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 26 Aug 2023 17:06:12 +0100 Subject: [PATCH 1/3] refactor: separate interfaces from project ready for unit testing --- .../Configuration/IBotConfiguration.cs | 33 +++++++++++++++++ .../Configuration/IChatConfiguration.cs | 21 +++++++++++ .../Configuration/IDiscordConfiguration.cs | 19 ++++++++++ .../IVirtualParadiseConfiguration.cs | 37 +++++++++++++++++++ .../Data/RelayedMessage.cs | 2 +- .../Services/IAvatarService.cs | 2 +- .../Services/IConfigurationService.cs | 10 ++--- .../Services/IDiscordMessageService.cs | 4 +- .../Services/IRelayTarget.cs | 4 +- .../IVirtualParadiseMessageService.cs | 4 +- VPLink.Common/VPLink.Common.csproj | 13 +++++++ VPLink.sln | 8 +++- VPLink/Configuration/BotConfiguration.cs | 31 ++++------------ VPLink/Configuration/ChatConfiguration.cs | 17 +++------ VPLink/Configuration/DiscordConfiguration.cs | 18 +++------ .../VirtualParadiseConfiguration.cs | 35 +++++------------- VPLink/Program.cs | 1 + VPLink/Services/AvatarService.cs | 7 ++-- VPLink/Services/ConfigurationService.cs | 8 ++-- VPLink/Services/DiscordMessageService.cs | 8 ++-- VPLink/Services/DiscordService.cs | 5 ++- VPLink/Services/RelayService.cs | 1 + .../Services/VirtualParadiseMessageService.cs | 9 +++-- VPLink/Services/VirtualParadiseService.cs | 5 ++- VPLink/VPLink.csproj | 4 ++ 25 files changed, 202 insertions(+), 104 deletions(-) create mode 100644 VPLink.Common/Configuration/IBotConfiguration.cs create mode 100644 VPLink.Common/Configuration/IChatConfiguration.cs create mode 100644 VPLink.Common/Configuration/IDiscordConfiguration.cs create mode 100644 VPLink.Common/Configuration/IVirtualParadiseConfiguration.cs rename {VPLink => VPLink.Common}/Data/RelayedMessage.cs (96%) rename {VPLink => VPLink.Common}/Services/IAvatarService.cs (96%) rename {VPLink => VPLink.Common}/Services/IConfigurationService.cs (68%) rename {VPLink => VPLink.Common}/Services/IDiscordMessageService.cs (94%) rename {VPLink => VPLink.Common}/Services/IRelayTarget.cs (87%) rename {VPLink => VPLink.Common}/Services/IVirtualParadiseMessageService.cs (89%) create mode 100644 VPLink.Common/VPLink.Common.csproj diff --git a/VPLink.Common/Configuration/IBotConfiguration.cs b/VPLink.Common/Configuration/IBotConfiguration.cs new file mode 100644 index 0000000..ecffb1e --- /dev/null +++ b/VPLink.Common/Configuration/IBotConfiguration.cs @@ -0,0 +1,33 @@ +namespace VPLink.Common.Configuration; + +/// +/// Represents the bot configuration. +/// +public interface IBotConfiguration +{ + /// + /// Gets a value indicating whether the bot should announce avatar events. + /// + /// + /// if the bot should announce avatar events; otherwise, . + /// + bool AnnounceAvatarEvents { get; } + + /// + /// Gets a value indicating whether the bot should announce avatar events for bots. + /// + /// + /// if the bot should announce avatar events for bots; otherwise, + /// . + /// + bool AnnounceBots { get; } + + /// + /// Gets a value indicating whether the bot should relay messages from other bots. + /// + /// + /// if the bot should relay messages from other bots; otherwise, + /// . + /// + bool RelayBotMessages { get; } +} diff --git a/VPLink.Common/Configuration/IChatConfiguration.cs b/VPLink.Common/Configuration/IChatConfiguration.cs new file mode 100644 index 0000000..86351a5 --- /dev/null +++ b/VPLink.Common/Configuration/IChatConfiguration.cs @@ -0,0 +1,21 @@ +using VpSharp; + +namespace VPLink.Common.Configuration; + +/// +/// Represents the chat configuration. +/// +public interface IChatConfiguration +{ + /// + /// Gets or sets the color of the message. + /// + /// The message color. + uint Color { get; set; } + + /// + /// Gets or sets the font style of the message. + /// + /// The font style. + FontStyle Style { get; set; } +} diff --git a/VPLink.Common/Configuration/IDiscordConfiguration.cs b/VPLink.Common/Configuration/IDiscordConfiguration.cs new file mode 100644 index 0000000..ae927b9 --- /dev/null +++ b/VPLink.Common/Configuration/IDiscordConfiguration.cs @@ -0,0 +1,19 @@ +namespace VPLink.Common.Configuration; + +/// +/// Represents the Discord configuration. +/// +public interface IDiscordConfiguration +{ + /// + /// Gets the channel ID to which the bot should relay messages. + /// + /// The channel ID. + ulong ChannelId { get; } + + /// + /// Gets the Discord token. + /// + /// The Discord token. + string Token { get; } +} diff --git a/VPLink.Common/Configuration/IVirtualParadiseConfiguration.cs b/VPLink.Common/Configuration/IVirtualParadiseConfiguration.cs new file mode 100644 index 0000000..956cc68 --- /dev/null +++ b/VPLink.Common/Configuration/IVirtualParadiseConfiguration.cs @@ -0,0 +1,37 @@ +namespace VPLink.Common.Configuration; + +/// +/// Represents the Virtual Paradise configuration. +/// +public interface IVirtualParadiseConfiguration +{ + /// + /// Gets or sets the display name of the bot. + /// + /// The display name. + string BotName { get; set; } + + /// + /// Gets or sets the chat configuration. + /// + /// The chat configuration. + IChatConfiguration Chat { get; } + + /// + /// Gets or sets the password with which to log in to Virtual Paradise. + /// + /// The login password. + string Password { get; set; } + + /// + /// Gets or sets the username with which to log in to Virtual Paradise. + /// + /// The login username. + string Username { get; set; } + + /// + /// Gets or sets the world into which the bot should enter. + /// + /// The world to enter. + string World { get; set; } +} diff --git a/VPLink/Data/RelayedMessage.cs b/VPLink.Common/Data/RelayedMessage.cs similarity index 96% rename from VPLink/Data/RelayedMessage.cs rename to VPLink.Common/Data/RelayedMessage.cs index 07b1469..b4f9886 100644 --- a/VPLink/Data/RelayedMessage.cs +++ b/VPLink.Common/Data/RelayedMessage.cs @@ -1,4 +1,4 @@ -namespace VPLink.Data; +namespace VPLink.Common.Data; /// /// Represents a message that is relayed between Discord and Virtual Paradise. diff --git a/VPLink/Services/IAvatarService.cs b/VPLink.Common/Services/IAvatarService.cs similarity index 96% rename from VPLink/Services/IAvatarService.cs rename to VPLink.Common/Services/IAvatarService.cs index 0bee759..5317f4a 100644 --- a/VPLink/Services/IAvatarService.cs +++ b/VPLink.Common/Services/IAvatarService.cs @@ -1,6 +1,6 @@ using VpSharp.Entities; -namespace VPLink.Services; +namespace VPLink.Common.Services; /// /// Represents a service that listens for, and triggers, avatar events. diff --git a/VPLink/Services/IConfigurationService.cs b/VPLink.Common/Services/IConfigurationService.cs similarity index 68% rename from VPLink/Services/IConfigurationService.cs rename to VPLink.Common/Services/IConfigurationService.cs index c8d657e..cfefe26 100644 --- a/VPLink/Services/IConfigurationService.cs +++ b/VPLink.Common/Services/IConfigurationService.cs @@ -1,6 +1,6 @@ -using VPLink.Configuration; +using VPLink.Common.Configuration; -namespace VPLink.Services; +namespace VPLink.Common.Services; /// /// Represents the configuration service. @@ -11,17 +11,17 @@ public interface IConfigurationService /// Gets the bot configuration. /// /// The bot configuration. - BotConfiguration BotConfiguration { get; } + IBotConfiguration BotConfiguration { get; } /// /// Gets the Discord configuration. /// /// The Discord configuration. - DiscordConfiguration DiscordConfiguration { get; } + IDiscordConfiguration DiscordConfiguration { get; } /// /// Gets the Virtual Paradise configuration. /// /// The Virtual Paradise configuration. - VirtualParadiseConfiguration VirtualParadiseConfiguration { get; } + IVirtualParadiseConfiguration VirtualParadiseConfiguration { get; } } diff --git a/VPLink/Services/IDiscordMessageService.cs b/VPLink.Common/Services/IDiscordMessageService.cs similarity index 94% rename from VPLink/Services/IDiscordMessageService.cs rename to VPLink.Common/Services/IDiscordMessageService.cs index b338686..c9a5009 100644 --- a/VPLink/Services/IDiscordMessageService.cs +++ b/VPLink.Common/Services/IDiscordMessageService.cs @@ -1,7 +1,7 @@ -using VPLink.Data; +using VPLink.Common.Data; using VpSharp.Entities; -namespace VPLink.Services; +namespace VPLink.Common.Services; /// /// Represents a service that listens for messages from the Discord bridge channel. diff --git a/VPLink/Services/IRelayTarget.cs b/VPLink.Common/Services/IRelayTarget.cs similarity index 87% rename from VPLink/Services/IRelayTarget.cs rename to VPLink.Common/Services/IRelayTarget.cs index e5a6cd6..4fe6987 100644 --- a/VPLink/Services/IRelayTarget.cs +++ b/VPLink.Common/Services/IRelayTarget.cs @@ -1,6 +1,6 @@ -using VPLink.Data; +using VPLink.Common.Data; -namespace VPLink.Services; +namespace VPLink.Common.Services; /// /// Represents an object that can be used as a relay target. diff --git a/VPLink/Services/IVirtualParadiseMessageService.cs b/VPLink.Common/Services/IVirtualParadiseMessageService.cs similarity index 89% rename from VPLink/Services/IVirtualParadiseMessageService.cs rename to VPLink.Common/Services/IVirtualParadiseMessageService.cs index a08ed6a..a6fc294 100644 --- a/VPLink/Services/IVirtualParadiseMessageService.cs +++ b/VPLink.Common/Services/IVirtualParadiseMessageService.cs @@ -1,6 +1,6 @@ -using VPLink.Data; +using VPLink.Common.Data; -namespace VPLink.Services; +namespace VPLink.Common.Services; /// /// Represents a service that listens for messages from the Virtual Paradise world. diff --git a/VPLink.Common/VPLink.Common.csproj b/VPLink.Common/VPLink.Common.csproj new file mode 100644 index 0000000..4c50db9 --- /dev/null +++ b/VPLink.Common/VPLink.Common.csproj @@ -0,0 +1,13 @@ + + + + net7.0 + enable + enable + + + + + + + diff --git a/VPLink.sln b/VPLink.sln index 104038c..986637f 100644 --- a/VPLink.sln +++ b/VPLink.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VPLink", "VPLink\VPLink.csproj", "{CD488A1E-0232-4EB5-A381-38A42B267B11}" EndProject @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{ .github\workflows\release.yml = .github\workflows\release.yml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VPLink.Common", "VPLink.Common\VPLink.Common.csproj", "{F1CE3BA6-05AC-47F3-BB7E-C489DC132367}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -29,5 +31,9 @@ Global {CD488A1E-0232-4EB5-A381-38A42B267B11}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD488A1E-0232-4EB5-A381-38A42B267B11}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD488A1E-0232-4EB5-A381-38A42B267B11}.Release|Any CPU.Build.0 = Release|Any CPU + {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/VPLink/Configuration/BotConfiguration.cs b/VPLink/Configuration/BotConfiguration.cs index c1b92e5..cd19664 100644 --- a/VPLink/Configuration/BotConfiguration.cs +++ b/VPLink/Configuration/BotConfiguration.cs @@ -1,33 +1,16 @@ +using VPLink.Common.Configuration; + namespace VPLink.Configuration; -/// -/// Represents the bot configuration. -/// -public sealed class BotConfiguration +/// +internal sealed class BotConfiguration : IBotConfiguration { - /// - /// Gets or sets a value indicating whether the bot should announce avatar events. - /// - /// - /// if the bot should announce avatar events; otherwise, . - /// + /// public bool AnnounceAvatarEvents { get; set; } = true; - /// - /// Gets or sets a value indicating whether the bot should announce avatar events for bots. - /// - /// - /// if the bot should announce avatar events for bots; otherwise, - /// . - /// + /// public bool AnnounceBots { get; set; } = false; - /// - /// Gets or sets a value indicating whether the bot should relay messages from other bots. - /// - /// - /// if the bot should relay messages from other bots; otherwise, - /// . - /// + /// public bool RelayBotMessages { get; set; } = false; } diff --git a/VPLink/Configuration/ChatConfiguration.cs b/VPLink/Configuration/ChatConfiguration.cs index dd99157..7fe03cb 100644 --- a/VPLink/Configuration/ChatConfiguration.cs +++ b/VPLink/Configuration/ChatConfiguration.cs @@ -1,21 +1,14 @@ +using VPLink.Common.Configuration; using VpSharp; namespace VPLink.Configuration; -/// -/// Represents the chat configuration. -/// -public sealed class ChatConfiguration +/// +internal sealed class ChatConfiguration : IChatConfiguration { - /// - /// Gets or sets the color of the message. - /// - /// The message color. + /// public uint Color { get; set; } = 0x191970; - /// - /// Gets or sets the font style of the message. - /// - /// The font style. + /// public FontStyle Style { get; set; } = FontStyle.Regular; } diff --git a/VPLink/Configuration/DiscordConfiguration.cs b/VPLink/Configuration/DiscordConfiguration.cs index e9b473a..a1aae0e 100644 --- a/VPLink/Configuration/DiscordConfiguration.cs +++ b/VPLink/Configuration/DiscordConfiguration.cs @@ -1,19 +1,13 @@ +using VPLink.Common.Configuration; + namespace VPLink.Configuration; -/// -/// Represents the Discord configuration. -/// -public sealed class DiscordConfiguration +/// +internal sealed class DiscordConfiguration : IDiscordConfiguration { - /// - /// Gets or sets the channel ID to which the bot should relay messages. - /// - /// The channel ID. + /// public ulong ChannelId { get; set; } - /// - /// Gets or sets the Discord token. - /// - /// The Discord token. + /// public string Token { get; set; } = string.Empty; } diff --git a/VPLink/Configuration/VirtualParadiseConfiguration.cs b/VPLink/Configuration/VirtualParadiseConfiguration.cs index 53b8f09..b77774a 100644 --- a/VPLink/Configuration/VirtualParadiseConfiguration.cs +++ b/VPLink/Configuration/VirtualParadiseConfiguration.cs @@ -1,37 +1,22 @@ +using VPLink.Common.Configuration; + namespace VPLink.Configuration; -/// -/// Represents the Virtual Paradise configuration. -/// -public sealed class VirtualParadiseConfiguration +/// +internal sealed class VirtualParadiseConfiguration : IVirtualParadiseConfiguration { - /// - /// Gets or sets the display name of the bot. - /// - /// The display name. + /// public string BotName { get; set; } = "VPLink"; - /// - /// Gets or sets the chat configuration. - /// - /// The chat configuration. - public ChatConfiguration Chat { get; } = new(); + /// + public IChatConfiguration Chat { get; } = new ChatConfiguration(); - /// - /// Gets or sets the password with which to log in to Virtual Paradise. - /// - /// The login password. + /// public string Password { get; set; } = string.Empty; - /// - /// Gets or sets the username with which to log in to Virtual Paradise. - /// - /// The login username. + /// public string Username { get; set; } = string.Empty; - /// - /// Gets or sets the world into which the bot should enter. - /// - /// The world to enter. + /// public string World { get; set; } = string.Empty; } diff --git a/VPLink/Program.cs b/VPLink/Program.cs index 48613e0..2cb9a15 100644 --- a/VPLink/Program.cs +++ b/VPLink/Program.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Serilog; using Tomlyn.Extensions.Configuration; +using VPLink.Common.Services; using VPLink.Services; using VpSharp; using X10D.Hosting.DependencyInjection; diff --git a/VPLink/Services/AvatarService.cs b/VPLink/Services/AvatarService.cs index 15c74d1..f2d5a80 100644 --- a/VPLink/Services/AvatarService.cs +++ b/VPLink/Services/AvatarService.cs @@ -2,7 +2,8 @@ using System.Reactive.Linq; using System.Reactive.Subjects; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using VPLink.Configuration; +using VPLink.Common.Configuration; +using VPLink.Common.Services; using VpSharp; using VpSharp.Entities; @@ -50,7 +51,7 @@ internal sealed class AvatarService : BackgroundService, IAvatarService { _logger.LogInformation("{Avatar} joined", avatar); - BotConfiguration configuration = _configurationService.BotConfiguration; + IBotConfiguration configuration = _configurationService.BotConfiguration; if (!configuration.AnnounceAvatarEvents || avatar.IsBot && !configuration.AnnounceBots) return; @@ -61,7 +62,7 @@ internal sealed class AvatarService : BackgroundService, IAvatarService { _logger.LogInformation("{Avatar} left", avatar); - BotConfiguration configuration = _configurationService.BotConfiguration; + IBotConfiguration configuration = _configurationService.BotConfiguration; if (!configuration.AnnounceAvatarEvents || avatar.IsBot && !configuration.AnnounceBots) return; diff --git a/VPLink/Services/ConfigurationService.cs b/VPLink/Services/ConfigurationService.cs index 1ce3939..3b915a1 100644 --- a/VPLink/Services/ConfigurationService.cs +++ b/VPLink/Services/ConfigurationService.cs @@ -1,4 +1,6 @@ using Microsoft.Extensions.Configuration; +using VPLink.Common.Configuration; +using VPLink.Common.Services; using VPLink.Configuration; namespace VPLink.Services; @@ -18,19 +20,19 @@ internal sealed class ConfigurationService : IConfigurationService } /// - public BotConfiguration BotConfiguration + public IBotConfiguration BotConfiguration { get => _configuration.GetSection("Bot").Get() ?? new BotConfiguration(); } /// - public DiscordConfiguration DiscordConfiguration + public IDiscordConfiguration DiscordConfiguration { get => _configuration.GetSection("Discord").Get() ?? new DiscordConfiguration(); } /// - public VirtualParadiseConfiguration VirtualParadiseConfiguration + public IVirtualParadiseConfiguration VirtualParadiseConfiguration { get => _configuration.GetSection("VirtualParadise").Get() ?? new VirtualParadiseConfiguration(); diff --git a/VPLink/Services/DiscordMessageService.cs b/VPLink/Services/DiscordMessageService.cs index c4f344a..d50bd8e 100644 --- a/VPLink/Services/DiscordMessageService.cs +++ b/VPLink/Services/DiscordMessageService.cs @@ -8,9 +8,11 @@ using Discord; using Discord.WebSocket; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using VPLink.Configuration; -using VPLink.Data; +using VPLink.Common.Configuration; +using VPLink.Common.Data; +using VPLink.Common.Services; using VpSharp.Entities; +using IUser = Discord.IUser; namespace VPLink.Services; @@ -144,7 +146,7 @@ internal sealed partial class DiscordMessageService : BackgroundService, IDiscor private bool TryGetRelayChannel([NotNullWhen(true)] out ITextChannel? channel) { - DiscordConfiguration configuration = _configurationService.DiscordConfiguration; + IDiscordConfiguration configuration = _configurationService.DiscordConfiguration; ulong channelId = configuration.ChannelId; if (_discordClient.GetChannel(channelId) is ITextChannel textChannel) diff --git a/VPLink/Services/DiscordService.cs b/VPLink/Services/DiscordService.cs index e01f909..530bf02 100644 --- a/VPLink/Services/DiscordService.cs +++ b/VPLink/Services/DiscordService.cs @@ -4,7 +4,8 @@ using Discord.WebSocket; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using VPLink.Commands; -using VPLink.Configuration; +using VPLink.Common.Configuration; +using VPLink.Common.Services; namespace VPLink.Services; @@ -48,7 +49,7 @@ internal sealed class DiscordService : BackgroundService _discordClient.Ready += OnReady; _discordClient.InteractionCreated += OnInteractionCreated; - DiscordConfiguration configuration = _configurationService.DiscordConfiguration; + IDiscordConfiguration configuration = _configurationService.DiscordConfiguration; string token = configuration.Token ?? throw new InvalidOperationException("Token is not set."); _logger.LogDebug("Connecting to Discord"); diff --git a/VPLink/Services/RelayService.cs b/VPLink/Services/RelayService.cs index 791e640..dd7087c 100644 --- a/VPLink/Services/RelayService.cs +++ b/VPLink/Services/RelayService.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using VPLink.Common.Services; using VpSharp.Extensions; namespace VPLink.Services; diff --git a/VPLink/Services/VirtualParadiseMessageService.cs b/VPLink/Services/VirtualParadiseMessageService.cs index cec294f..be7c784 100644 --- a/VPLink/Services/VirtualParadiseMessageService.cs +++ b/VPLink/Services/VirtualParadiseMessageService.cs @@ -3,15 +3,16 @@ using System.Reactive.Linq; using System.Reactive.Subjects; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using VPLink.Configuration; -using VPLink.Data; +using VPLink.Common.Configuration; +using VPLink.Common.Data; +using VPLink.Common.Services; using VpSharp; using VpSharp.Entities; using FontStyle = VpSharp.FontStyle; namespace VPLink.Services; -/// +/// internal sealed class VirtualParadiseMessageService : BackgroundService, IVirtualParadiseMessageService { private readonly ILogger _logger; @@ -40,7 +41,7 @@ internal sealed class VirtualParadiseMessageService : BackgroundService, IVirtua /// public Task SendMessageAsync(RelayedMessage message) { - ChatConfiguration configuration = _configurationService.VirtualParadiseConfiguration.Chat; + IChatConfiguration configuration = _configurationService.VirtualParadiseConfiguration.Chat; Color color = Color.FromArgb((int)configuration.Color); FontStyle style = configuration.Style; diff --git a/VPLink/Services/VirtualParadiseService.cs b/VPLink/Services/VirtualParadiseService.cs index dc15115..5036d9e 100644 --- a/VPLink/Services/VirtualParadiseService.cs +++ b/VPLink/Services/VirtualParadiseService.cs @@ -1,9 +1,10 @@ using System.Reactive.Subjects; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using VPLink.Common.Configuration; +using VPLink.Common.Services; using VpSharp; using VpSharp.Entities; -using VirtualParadiseConfiguration = VPLink.Configuration.VirtualParadiseConfiguration; namespace VPLink.Services; @@ -35,7 +36,7 @@ internal sealed class VirtualParadiseService : BackgroundService _logger.LogInformation("Establishing relay"); _virtualParadiseClient.MessageReceived.Subscribe(_messageReceived); - VirtualParadiseConfiguration configuration = _configurationService.VirtualParadiseConfiguration; + IVirtualParadiseConfiguration configuration = _configurationService.VirtualParadiseConfiguration; string username = configuration.Username ?? throw new InvalidOperationException("Username is not set."); string password = configuration.Password ?? throw new InvalidOperationException("Password is not set."); diff --git a/VPLink/VPLink.csproj b/VPLink/VPLink.csproj index 78f73df..7b45bd8 100644 --- a/VPLink/VPLink.csproj +++ b/VPLink/VPLink.csproj @@ -55,4 +55,8 @@ + + + + From 742322236abdd8ea57e0932079813e1a275628ee Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 26 Aug 2023 17:06:36 +0100 Subject: [PATCH 2/3] tests: add boilerplate test project --- VPLink.Tests/GlobalUsings.cs | 1 + VPLink.Tests/UnitTest1.cs | 15 +++++++++++++++ VPLink.Tests/VPLink.Tests.csproj | 20 ++++++++++++++++++++ VPLink.sln | 8 +++++++- 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 VPLink.Tests/GlobalUsings.cs create mode 100644 VPLink.Tests/UnitTest1.cs create mode 100644 VPLink.Tests/VPLink.Tests.csproj diff --git a/VPLink.Tests/GlobalUsings.cs b/VPLink.Tests/GlobalUsings.cs new file mode 100644 index 0000000..3244567 --- /dev/null +++ b/VPLink.Tests/GlobalUsings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; diff --git a/VPLink.Tests/UnitTest1.cs b/VPLink.Tests/UnitTest1.cs new file mode 100644 index 0000000..e27f1e1 --- /dev/null +++ b/VPLink.Tests/UnitTest1.cs @@ -0,0 +1,15 @@ +namespace VPLink.Tests; + +public class Tests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public void Test1() + { + Assert.Pass(); + } +} diff --git a/VPLink.Tests/VPLink.Tests.csproj b/VPLink.Tests/VPLink.Tests.csproj new file mode 100644 index 0000000..226d57f --- /dev/null +++ b/VPLink.Tests/VPLink.Tests.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + + + + + diff --git a/VPLink.sln b/VPLink.sln index 986637f..5152bbb 100644 --- a/VPLink.sln +++ b/VPLink.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VPLink", "VPLink\VPLink.csproj", "{CD488A1E-0232-4EB5-A381-38A42B267B11}" EndProject @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{ .github\workflows\release.yml = .github\workflows\release.yml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VPLink.Tests", "VPLink.Tests\VPLink.Tests.csproj", "{17F63B22-1E27-4438-8C76-7E89706713E8}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VPLink.Common", "VPLink.Common\VPLink.Common.csproj", "{F1CE3BA6-05AC-47F3-BB7E-C489DC132367}" EndProject Global @@ -31,6 +33,10 @@ Global {CD488A1E-0232-4EB5-A381-38A42B267B11}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD488A1E-0232-4EB5-A381-38A42B267B11}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD488A1E-0232-4EB5-A381-38A42B267B11}.Release|Any CPU.Build.0 = Release|Any CPU + {17F63B22-1E27-4438-8C76-7E89706713E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17F63B22-1E27-4438-8C76-7E89706713E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17F63B22-1E27-4438-8C76-7E89706713E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17F63B22-1E27-4438-8C76-7E89706713E8}.Release|Any CPU.Build.0 = Release|Any CPU {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Debug|Any CPU.Build.0 = Debug|Any CPU {F1CE3BA6-05AC-47F3-BB7E-C489DC132367}.Release|Any CPU.ActiveCfg = Release|Any CPU From 2925de032934b177784dbca4df0256d1af69c022 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 26 Aug 2023 17:47:11 +0100 Subject: [PATCH 3/3] tests: add preliminary relay tests --- VPLink.Tests/BotConfigurationTests.cs | 35 ++++++++++ VPLink.Tests/DiscordConfigurationTests.cs | 33 ++++++++++ VPLink.Tests/RelayTests.cs | 64 +++++++++++++++++++ VPLink.Tests/UnitTest1.cs | 15 ----- VPLink.Tests/VPLink.Tests.csproj | 5 ++ .../VirtualParadiseConfigurationTests.cs | 37 +++++++++++ 6 files changed, 174 insertions(+), 15 deletions(-) create mode 100644 VPLink.Tests/BotConfigurationTests.cs create mode 100644 VPLink.Tests/DiscordConfigurationTests.cs create mode 100644 VPLink.Tests/RelayTests.cs delete mode 100644 VPLink.Tests/UnitTest1.cs create mode 100644 VPLink.Tests/VirtualParadiseConfigurationTests.cs diff --git a/VPLink.Tests/BotConfigurationTests.cs b/VPLink.Tests/BotConfigurationTests.cs new file mode 100644 index 0000000..5239270 --- /dev/null +++ b/VPLink.Tests/BotConfigurationTests.cs @@ -0,0 +1,35 @@ +using NSubstitute; +using NSubstitute.Extensions; +using VPLink.Common.Configuration; +using VPLink.Common.Services; + +namespace VPLink.Tests; + +public class BotConfigurationTests +{ + private IConfigurationService _configurationService = null!; + + [SetUp] + public void Setup() + { + var configuration = Substitute.For(); + configuration.AnnounceAvatarEvents.Returns(true); + configuration.AnnounceBots.Returns(false); + configuration.RelayBotMessages.Returns(false); + + _configurationService = Substitute.For(); + _configurationService.Configure().BotConfiguration.Returns(configuration); + } + + [Test] + public void BotConfiguration_ShouldReturnCorrectValues_GivenDefaultConfig() + { + IBotConfiguration configuration = _configurationService.BotConfiguration; + Assert.Multiple(() => + { + Assert.That(configuration.AnnounceAvatarEvents, Is.True); + Assert.That(configuration.AnnounceBots, Is.False); + Assert.That(configuration.RelayBotMessages, Is.False); + }); + } +} diff --git a/VPLink.Tests/DiscordConfigurationTests.cs b/VPLink.Tests/DiscordConfigurationTests.cs new file mode 100644 index 0000000..50bfefe --- /dev/null +++ b/VPLink.Tests/DiscordConfigurationTests.cs @@ -0,0 +1,33 @@ +using NSubstitute; +using NSubstitute.Extensions; +using VPLink.Common.Configuration; +using VPLink.Common.Services; + +namespace VPLink.Tests; + +public class DiscordConfigurationTests +{ + private IConfigurationService _configurationService = null!; + + [SetUp] + public void Setup() + { + var configuration = Substitute.For(); + configuration.Token.Returns("DISCORD_TOKEN"); + configuration.ChannelId.Returns(1234567890UL); + + _configurationService = Substitute.For(); + _configurationService.Configure().DiscordConfiguration.Returns(configuration); + } + + [Test] + public void DiscordConfiguration_ShouldReturnCorrectValues_GivenDefaultConfig() + { + IDiscordConfiguration configuration = _configurationService.DiscordConfiguration; + Assert.Multiple(() => + { + Assert.That(configuration.Token, Is.EqualTo("DISCORD_TOKEN")); + Assert.That(configuration.ChannelId, Is.EqualTo(1234567890UL)); + }); + } +} diff --git a/VPLink.Tests/RelayTests.cs b/VPLink.Tests/RelayTests.cs new file mode 100644 index 0000000..68a3ee1 --- /dev/null +++ b/VPLink.Tests/RelayTests.cs @@ -0,0 +1,64 @@ +using System.Reactive.Linq; +using System.Reactive.Subjects; +using NSubstitute; +using NSubstitute.Extensions; +using VPLink.Common.Data; +using VPLink.Common.Services; +using VpSharp.Extensions; + +namespace VPLink.Tests; + +public class RelayTests +{ + private readonly Subject _vpMessageReceived = new(); + private readonly Subject _discordMessageReceived = new(); + private IVirtualParadiseMessageService _vpMessageService = null!; + private IDiscordMessageService _discordMessageService = null!; + + [SetUp] + public void Setup() + { + _discordMessageService = Substitute.For(); + _discordMessageService.Configure().SendMessageAsync(Arg.Any()).Returns(Task.CompletedTask); + + _vpMessageService = Substitute.For(); + _vpMessageService.Configure().OnMessageReceived.Returns(_vpMessageReceived.AsObservable()); + + _discordMessageService = Substitute.For(); + _discordMessageService.Configure().OnMessageReceived.Returns(_discordMessageReceived.AsObservable()); + + _discordMessageReceived.SubscribeAsync(_vpMessageService.SendMessageAsync); + _vpMessageReceived.SubscribeAsync(_discordMessageService.SendMessageAsync); + } + + [Test] + public void VirtualParadiseMessage_ShouldRelay_ToDiscordService() + { + var observer = Substitute.For>(); + _vpMessageReceived.Subscribe(observer); + + const string author = "Admin"; + const string message = "Hello, world!"; + + _vpMessageReceived.OnNext(new RelayedMessage(author, message)); + + observer.Received(1).OnNext(Arg.Is(m => m.Author == author && m.Content == message)); + _discordMessageService.Received(1) + .SendMessageAsync(Arg.Is(m => m.Author == author && m.Content == message)); + } + + [Test] + public void DiscordMessage_ShouldRelay_ToVirtualParadiseService() + { + var observer = Substitute.For>(); + _discordMessageReceived.Subscribe(observer); + + const string author = "Admin"; + const string message = "Hello, world!"; + + _discordMessageReceived.OnNext(new RelayedMessage(author, message)); + + observer.Received(1).OnNext(Arg.Is(m => m.Author == author && m.Content == message)); + _vpMessageService.Received(1).SendMessageAsync(Arg.Is(m => m.Author == author && m.Content == message)); + } +} diff --git a/VPLink.Tests/UnitTest1.cs b/VPLink.Tests/UnitTest1.cs deleted file mode 100644 index e27f1e1..0000000 --- a/VPLink.Tests/UnitTest1.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace VPLink.Tests; - -public class Tests -{ - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - Assert.Pass(); - } -} diff --git a/VPLink.Tests/VPLink.Tests.csproj b/VPLink.Tests/VPLink.Tests.csproj index 226d57f..fd7977f 100644 --- a/VPLink.Tests/VPLink.Tests.csproj +++ b/VPLink.Tests/VPLink.Tests.csproj @@ -11,10 +11,15 @@ + + + + + diff --git a/VPLink.Tests/VirtualParadiseConfigurationTests.cs b/VPLink.Tests/VirtualParadiseConfigurationTests.cs new file mode 100644 index 0000000..c24f280 --- /dev/null +++ b/VPLink.Tests/VirtualParadiseConfigurationTests.cs @@ -0,0 +1,37 @@ +using NSubstitute; +using NSubstitute.Extensions; +using VPLink.Common.Configuration; +using VPLink.Common.Services; + +namespace VPLink.Tests; + +public class VirtualParadiseConfigurationTests +{ + private IConfigurationService _configurationService = null!; + + [SetUp] + public void Setup() + { + var configuration = Substitute.For(); + configuration.Username.Returns("Admin"); + configuration.Password.Returns("Password1234"); + configuration.World.Returns("Blizzard"); + configuration.BotName.Returns("VPLink"); + + _configurationService = Substitute.For(); + _configurationService.Configure().VirtualParadiseConfiguration.Returns(configuration); + } + + [Test] + public void DiscordConfiguration_ShouldReturnCorrectValues_GivenDefaultConfig() + { + IVirtualParadiseConfiguration configuration = _configurationService.VirtualParadiseConfiguration; + Assert.Multiple(() => + { + Assert.That(configuration.Username, Is.EqualTo("Admin")); + Assert.That(configuration.Password, Is.EqualTo("Password1234")); + Assert.That(configuration.World, Is.EqualTo("Blizzard")); + Assert.That(configuration.BotName, Is.EqualTo("VPLink")); + }); + } +}