diff --git a/README.md b/README.md index 0cf8de14e..76ec6a169 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ -# Discord.Net v0.9.0-rc3 +# Discord.Net v0.9.0-rc4 +[![Build status](https://ci.appveyor.com/api/projects/status/p0n69xhqgmoobycf/branch/master?svg=true)](https://ci.appveyor.com/project/foxbot/discord-net/branch/master) + An unofficial .Net API Wrapper for the Discord client (http://discordapp.com). Check out the [documentation](https://discordnet.readthedocs.org/en/latest/) or join the [Discord API Chat](https://discord.gg/0SBTUU1wZTVjAMPx). -##### Warning: documentation is currently outdated. +##### Warning: Some of the documentation is outdated. It's current being rewritten. Until that's done, feel free to use my [DiscordBot](https://github.com/RogueException/DiscordBot) repo for reference. ### Installation diff --git a/test/Discord.Net.Tests/Discord.Net.Tests.csproj b/test/Discord.Net.Tests/Discord.Net.Tests.csproj index 97d328c68..0136c7ea9 100644 --- a/test/Discord.Net.Tests/Discord.Net.Tests.csproj +++ b/test/Discord.Net.Tests/Discord.Net.Tests.csproj @@ -37,7 +37,7 @@ - ..\..\..\DiscordBot\packages\Newtonsoft.Json.8.0.1\lib\net45\Newtonsoft.Json.dll + ..\..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll True @@ -56,7 +56,6 @@ - diff --git a/test/Discord.Net.Tests/Settings.cs b/test/Discord.Net.Tests/Settings.cs deleted file mode 100644 index 5aa37e184..000000000 --- a/test/Discord.Net.Tests/Settings.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Newtonsoft.Json; -using System.IO; - -namespace Discord.Tests -{ - internal class Settings - { - private const string path = "../../config.json"; - public static readonly Settings Instance; - static Settings() - { - if (!File.Exists(path)) - throw new FileNotFoundException("config.json is missing, rename config.json.example and add credentials for three separate unused accounts for testing."); - Instance = JsonConvert.DeserializeObject(File.ReadAllText(path)); - } - - public class Account - { - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("password")] - public string Password { get; set; } - } - - [JsonProperty("user1")] - public Account User1 { get; set; } - [JsonProperty("user2")] - public Account User2 { get; set; } - [JsonProperty("user3")] - public Account User3 { get; set; } - } -} diff --git a/test/Discord.Net.Tests/Tests.cs b/test/Discord.Net.Tests/Tests.cs index e3d3977ad..1808cfa65 100644 --- a/test/Discord.Net.Tests/Tests.cs +++ b/test/Discord.Net.Tests/Tests.cs @@ -7,165 +7,485 @@ using System.Threading.Tasks; namespace Discord.Tests { - //TODO: Tests are massively incomplete and out of date, needing a full rewrite + //TODO: Tests are massively incomplete and out of date, needing a full rewrite + + [TestClass] + public class Tests + { + private const int EventTimeout = 10000; //Max time in milliseconds to wait for an event response from our test actions - [TestClass] - public class Tests - { - private const int EventTimeout = 5000; //Max time in milliseconds to wait for an event response from our test actions - private static DiscordClient _hostClient, _targetBot, _observerBot; - private static Server _testServer; - private static Channel _testServerChannel; - private static Random _random; - - [ClassInitialize] - public static void Initialize(TestContext testContext) - { - var settings = Settings.Instance; - _random = new Random(); - - _hostClient = new DiscordClient(); - _targetBot = new DiscordClient(); - _observerBot = new DiscordClient(); - - _hostClient.Connect(settings.User1.Email, settings.User1.Password).Wait(); - _targetBot.Connect(settings.User2.Email, settings.User2.Password).Wait(); - _observerBot.Connect(settings.User3.Email, settings.User3.Password).Wait(); - - //Cleanup existing servers - WaitMany( - _hostClient.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()), - _targetBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()), - _observerBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave())); - - //Create new server and invite the other bots to it - _testServer = _hostClient.CreateServer("Discord.Net Testing", _hostClient.Regions.First()).Result; - _testServerChannel = _testServer.DefaultChannel; - Invite invite = _testServer.CreateInvite(60, 1, false, false).Result; - WaitAll( - _targetBot.GetInvite(invite.Code).Result.Accept(), - _observerBot.GetInvite(invite.Code).Result.Accept()); - } - - //Channels - [TestMethod] - public void TestCreateTextChannel() - => TestCreateChannel(ChannelType.Text); - [TestMethod] - public void TestCreateVoiceChannel() - => TestCreateChannel(ChannelType.Voice); - private void TestCreateChannel(ChannelType type) - { - Channel channel = null; - string name = $"#test_{_random.Next()}"; - AssertEvent( - "ChannelCreated event never received", - async () => channel = await _testServer.CreateChannel(name.Substring(1), type), - x => _targetBot.ChannelCreated += x, - x => _targetBot.ChannelCreated -= x, - (s, e) => e.Channel.Name == name); - - AssertEvent( - "ChannelDestroyed event never received", - async () => await channel.Delete(), - x => _targetBot.ChannelDestroyed += x, - x => _targetBot.ChannelDestroyed -= x, - (s, e) => e.Channel.Name == name); - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public async Task TestCreateChannel_NoName() - { - await _testServer.CreateChannel($"", ChannelType.Text); - } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public async Task TestCreateChannel_NoType() - { - string name = $"#test_{_random.Next()}"; - await _testServer.CreateChannel($"", ChannelType.FromString("")); - } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public async Task TestCreateChannel_BadType() - { - string name = $"#test_{_random.Next()}"; - await _testServer.CreateChannel($"", ChannelType.FromString("badtype")); - } - - //Messages - [TestMethod] - public void TestSendMessage() - { - string text = $"test_{_random.Next()}"; - AssertEvent( - "MessageCreated event never received", - () => _testServerChannel.SendMessage(text), - x => _targetBot.MessageReceived += x, - x => _targetBot.MessageReceived -= x, - (s, e) => e.Message.Text == text); - } - - [ClassCleanup] - public static void Cleanup() - { - WaitMany( - _hostClient.State == ConnectionState.Connected ? _hostClient.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null, - _targetBot.State == ConnectionState.Connected ? _targetBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null, - _observerBot.State == ConnectionState.Connected ? _observerBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null); - - WaitAll( - _hostClient.Disconnect(), - _targetBot.Disconnect(), - _observerBot.Disconnect()); - } - - private static void AssertEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test = null) - { - AssertEvent(msg, action, addEvent, removeEvent, test, true); - } - private static void AssertNoEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test = null) - { - AssertEvent(msg, action, addEvent, removeEvent, test, false); - } - private static void AssertEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test, bool assertTrue) - { - ManualResetEventSlim trigger = new ManualResetEventSlim(false); - bool result = false; - - EventHandler handler = (s, e) => - { - if (test != null) - { - result |= test(s, e); - trigger.Set(); + private static Server _testServer; + private static Channel _testServerChannel; + private static Channel _permRestrictedChannel; + private static Random _random; + private static Invite _testServerInvite; + + private static TestContext _context; + + private static string HostBotToken; + private static string ObserverBotToken; + private static string TargetEmail; + private static string TargetPassword; + + public static string RandomText => $"test_{_random.Next()}"; + + #region Initialization + + [ClassInitialize] + public static void Initialize(TestContext testContext) + { + _context = testContext; + + HostBotToken = Environment.GetEnvironmentVariable("discord-unit-host_token"); + ObserverBotToken = Environment.GetEnvironmentVariable("discord-unit-observer_token"); + TargetEmail = Environment.GetEnvironmentVariable("discord-unit-target_email"); + TargetPassword = Environment.GetEnvironmentVariable("discord-unit-target_pass"); + } + + [TestMethod] + [Priority(1)] + public async Task TestInitialize() + { + _context.WriteLine("Initializing."); + + _random = new Random(); + + _hostClient = new DiscordClient(); + _targetBot = new DiscordClient(); + _observerBot = new DiscordClient(); + + await _hostClient.Connect(HostBotToken); + + await Task.Delay(3000); + + //Cleanup existing servers + _hostClient.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()); + + //Create new server and invite the other bots to it + + _testServer = await _hostClient.CreateServer("Discord.Net Testing", _hostClient.Regions.First()); + + await Task.Delay(1000); + + Invite invite = await _testServer.CreateInvite(60, 3, false, false); + _testServerInvite = invite; + + _context.WriteLine($"Host: {_hostClient.CurrentUser.Name} in {_hostClient.Servers.Count()}"); + } + + [TestMethod] + [Priority(2)] + public async Task TestTokenLogin_Ready() + { + AssertEvent( + "READY never received", + async () => await _observerBot.Connect(ObserverBotToken), + x => _observerBot.Ready += x, + x => _observerBot.Ready -= x, + null, + true); + _observerBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()); + await (await _observerBot.GetInvite(_testServerInvite.Code)).Accept(); + } + + [TestMethod] + [Priority(2)] + public void TestReady() + { + AssertEvent( + "READY never received", + async () => await _targetBot.Connect(TargetEmail, TargetPassword), + x => _targetBot.Ready += x, + x => _targetBot.Ready -= x, + null, + true); + + _targetBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()); + _testServerChannel = _testServer.DefaultChannel; + } + + #endregion + + // Servers + + #region Server Tests + + [TestMethod] + [Priority(3)] + public void TestJoinedServer() + { + AssertEvent( + "Never Got JoinedServer", + async () => await (await _targetBot.GetInvite(_testServerInvite.Code)).Accept(), + x => _targetBot.JoinedServer += x, + x => _targetBot.JoinedServer -= x); + } + + #endregion + + #region Channel Tests + + //Channels + [TestMethod] + public void TestCreateTextChannel() + => TestCreateChannel(ChannelType.Text); + [TestMethod] + public void TestCreateVoiceChannel() + => TestCreateChannel(ChannelType.Voice); + private void TestCreateChannel(ChannelType type) + { + _context.WriteLine($"Host: {_hostClient.CurrentUser.Name} in {_hostClient.Servers.Count()}"); + _context.WriteLine($"Target: {_targetBot.CurrentUser.Name} in {_targetBot.Servers.Count()}"); + _context.WriteLine($"Observer: {_observerBot.CurrentUser.Name} in {_observerBot.Servers.Count()}"); + Channel channel = null; + string name = $"test_{_random.Next()}"; + AssertEvent( + "ChannelCreated event never received", + async () => channel = await _testServer.CreateChannel(name, type), + x => _targetBot.ChannelCreated += x, + x => _targetBot.ChannelCreated -= x, + (s, e) => e.Channel.Name == name); + + AssertEvent( + "ChannelDestroyed event never received", + async () => await channel.Delete(), + x => _targetBot.ChannelDestroyed += x, + x => _targetBot.ChannelDestroyed -= x, + (s, e) => e.Channel.Name == name); + } + + [TestMethod] + [ExpectedException(typeof(Net.HttpException))] + public async Task TestCreateChannel_NoName() + { + await _testServer.CreateChannel($"", ChannelType.Text); + } + [TestMethod] + [ExpectedException(typeof(Net.HttpException))] + public async Task TestCreateChannel_NoType() + { + string name = $"#test_{_random.Next()}"; + await _testServer.CreateChannel($"", ChannelType.FromString("")); + } + [TestMethod] + [ExpectedException(typeof(Net.HttpException))] + public async Task TestCreateChannel_BadType() + { + string name = $"#test_{_random.Next()}"; + await _testServer.CreateChannel($"", ChannelType.FromString("badtype")); + } + [TestMethod] + public async Task Test_CreateGetChannel() + { + var name = $"test_{_random.Next()}"; + var channel = await _testServer.CreateChannel(name, ChannelType.Text); + var get_channel = _testServer.GetChannel(channel.Id); + Assert.AreEqual(channel.Id, get_channel.Id, "ID of Channel and GetChannel were not equal."); + } + [TestMethod] + public void TestSendTyping() + { + var channel = _testServerChannel; + AssertEvent( + "UserUpdated event never fired.", + async () => await channel.SendIsTyping(), + x => _targetBot.UserIsTyping += x, + x => _targetBot.UserIsTyping -= x); + } + [TestMethod] + public void TestEditChannel() + { + var channel = _testServerChannel; + AssertEvent( + "ChannelUpdated Never Received", + async () => await channel.Edit(RandomText, $"topic - {RandomText}", 26), + x => _targetBot.ChannelUpdated += x, + x => _targetBot.ChannelUpdated -= x); + } + [TestMethod] + public void TestChannelMention() + { + var channel = _testServerChannel; + Assert.AreEqual($"<#{channel.Id}>", channel.Mention, "Generated channel mention was not the expected channel mention."); + } + [TestMethod] + public void TestChannelUserCount() + { + Assert.AreEqual(3, _testServerChannel.Users.Count(), "Read an incorrect number of users in a channel"); + } + + #endregion + + #region Message Tests + + //Messages + [TestMethod] + public void TestMessageEvents() + { + string name = $"test_{_random.Next()}"; + var channel = _testServer.CreateChannel(name, ChannelType.Text).Result; + _context.WriteLine($"Channel Name: {channel.Name} / {channel.Server.Name}"); + string text = $"test_{_random.Next()}"; + Message message = null; + AssertEvent( + "MessageCreated event never received", + async () => message = await channel.SendMessage(text), + x => _targetBot.MessageReceived += x, + x => _targetBot.MessageReceived -= x, + (s, e) => e.Message.Text == text); + + AssertEvent( + "MessageUpdated event never received", + async () => await message.Edit(text + " updated"), + x => _targetBot.MessageUpdated += x, + x => _targetBot.MessageUpdated -= x, + (s, e) => e.Before.Text == text && e.After.Text == text + " updated"); + + AssertEvent( + "MessageDeleted event never received", + async () => await message.Delete(), + x => _targetBot.MessageDeleted += x, + x => _targetBot.MessageDeleted -= x, + (s, e) => e.Message.Id == message.Id); + } + [TestMethod] + public async Task TestDownloadMessages_WithCache() + { + string name = $"test_{_random.Next()}"; + var channel = await _testServer.CreateChannel(name, ChannelType.Text); + for (var i = 0; i < 10; i++) await channel.SendMessage(RandomText); + while (channel.Client.MessageQueue.Count > 0) await Task.Delay(100); + var messages = await channel.DownloadMessages(10); + Assert.AreEqual(10, messages.Count(), "Expected 10 messages in downloaded array, did not see 10."); + } + [TestMethod] + public async Task TestDownloadMessages_WithoutCache() + { + string name = $"test_{_random.Next()}"; + var channel = await _testServer.CreateChannel(name, ChannelType.Text); + for (var i = 0; i < 10; i++) await channel.SendMessage(RandomText); + while (channel.Client.MessageQueue.Count > 0) await Task.Delay(100); + var messages = await channel.DownloadMessages(10, useCache: false); + Assert.AreEqual(10, messages.Count(), "Expected 10 messages in downloaded array, did not see 10."); + } + [TestMethod] + public async Task TestSendTTSMessage() + { + var channel = await _testServer.CreateChannel(RandomText, ChannelType.Text); + AssertEvent( + "MessageCreated event never fired", + async () => await channel.SendTTSMessage(RandomText), + x => _targetBot.MessageReceived += x, + x => _targetBot.MessageReceived -= x, + (s, e) => e.Message.IsTTS); + } + + #endregion + + #region User Tests + + [TestMethod] + public void TestUserMentions() + { + var user = _targetBot.GetServer(_testServer.Id).CurrentUser; + Assert.AreEqual($"<@{user.Id}>", user.Mention); + } + [TestMethod] + public void TestUserEdit() + { + var user = _testServer.GetUser(_targetBot.CurrentUser.Id); + AssertEvent( + "UserUpdated never fired", + async () => await user.Edit(true, true, null, null), + x => _targetBot.UserUpdated += x, + x => _targetBot.UserUpdated -= x); + } + [TestMethod] + public void TestEditSelf() + { + var name = $"test_{_random.Next()}"; + AssertEvent( + "UserUpdated never fired", + async () => await _targetBot.CurrentUser.Edit(TargetPassword, name), + x => _observerBot.UserUpdated += x, + x => _observerBot.UserUpdated -= x, + (s, e) => e.After.Name == name); + } + [TestMethod] + public void TestSetStatus() + { + AssertEvent( + "UserUpdated never fired", + async () => await SetStatus(_targetBot, UserStatus.Idle), + x => _observerBot.UserUpdated += x, + x => _observerBot.UserUpdated -= x, + (s, e) => e.After.Status == UserStatus.Idle); + } + private async Task SetStatus(DiscordClient _client, UserStatus status) + { + _client.SetStatus(status); + await Task.Delay(50); + } + [TestMethod] + public void TestSetGame() + { + AssertEvent( + "UserUpdated never fired", + async () => await SetGame(_targetBot, "test game"), + x => _observerBot.UserUpdated += x, + x => _observerBot.UserUpdated -= x, + (s, e) => _targetBot.CurrentGame == "test game"); + + } + private async Task SetGame(DiscordClient _client, string game) + { + _client.SetGame(game); + await Task.Delay(5); + } + + #endregion + + #region Permission Tests + + // Permissions + [TestMethod] + public async Task Test_AddGet_PermissionsRule() + { + var channel = await _testServer.CreateChannel($"test_{_random.Next()}", ChannelType.Text); + var user = _testServer.GetUser(_targetBot.CurrentUser.Id); + var perms = new ChannelPermissionOverrides(sendMessages: PermValue.Deny); + await channel.AddPermissionsRule(user, perms); + var resultPerms = channel.GetPermissionsRule(user); + Assert.IsNotNull(resultPerms, "Perms retrieved from server were null."); + } + [TestMethod] + public async Task Test_AddRemove_PermissionsRule() + { + var channel = await _testServer.CreateChannel($"test_{_random.Next()}", ChannelType.Text); + var user = _testServer.GetUser(_targetBot.CurrentUser.Id); + var perms = new ChannelPermissionOverrides(sendMessages: PermValue.Deny); + await channel.AddPermissionsRule(user, perms); + await channel.RemovePermissionsRule(user); + await Task.Delay(200); + Assert.AreEqual(PermValue.Inherit, channel.GetPermissionsRule(user).SendMessages); + } + [TestMethod] + public async Task Test_Permissions_Event() + { + var channel = await _testServer.CreateChannel($"test_{_random.Next()}", ChannelType.Text); + var user = _testServer.GetUser(_targetBot.CurrentUser.Id); + var perms = new ChannelPermissionOverrides(sendMessages: PermValue.Deny); + AssertEvent + ("ChannelUpdatedEvent never fired.", + async () => await channel.AddPermissionsRule(user, perms), + x => _targetBot.ChannelUpdated += x, + x => _targetBot.ChannelUpdated -= x, + (s, e) => e.After.PermissionOverwrites.Count() != e.Before.PermissionOverwrites.Count()); + } + [TestMethod] + [ExpectedException(typeof(Net.HttpException))] + public async Task Test_Affect_Permissions_Invalid_Channel() + { + var channel = await _testServer.CreateChannel($"test_{_random.Next()}", ChannelType.Text); + var user = _testServer.GetUser(_targetBot.CurrentUser.Id); + var perms = new ChannelPermissionOverrides(sendMessages: PermValue.Deny); + await channel.Delete(); + await channel.AddPermissionsRule(user, perms); + } + + #endregion + + + [ClassCleanup] + public static void Cleanup() + { + WaitMany( + _hostClient.State == ConnectionState.Connected ? _hostClient.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null, + _targetBot.State == ConnectionState.Connected ? _targetBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null, + _observerBot.State == ConnectionState.Connected ? _observerBot.Servers.Select(x => x.IsOwner ? x.Delete() : x.Leave()) : null); + + WaitAll( + _hostClient.Disconnect(), + _targetBot.Disconnect(), + _observerBot.Disconnect()); + } + + #region Helpers + + // Task Helpers + + private static void AssertEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test = null) + { + AssertEvent(msg, action, addEvent, removeEvent, test, true); + } + private static void AssertNoEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test = null) + { + AssertEvent(msg, action, addEvent, removeEvent, test, false); + } + private static void AssertEvent(string msg, Func action, Action> addEvent, Action> removeEvent, Func test, bool assertTrue) + { + ManualResetEventSlim trigger = new ManualResetEventSlim(false); + bool result = false; + + EventHandler handler = (s, e) => + { + if (test != null) + { + result |= test(s, e); + trigger.Set(); } - else - result = true; - }; - - addEvent(handler); - var task = action(); - trigger.Wait(EventTimeout); - task.Wait(); - removeEvent(handler); - - Assert.AreEqual(assertTrue, result, msg); - } - - private static void WaitAll(params Task[] tasks) - { - Task.WaitAll(tasks); - } - private static void WaitAll(IEnumerable tasks) - { - Task.WaitAll(tasks.ToArray()); - } - private static void WaitMany(params IEnumerable[] tasks) - { - Task.WaitAll(tasks.Where(x => x != null).SelectMany(x => x).ToArray()); - } - } + else + result = true; + }; + + addEvent(handler); + var task = action(); + trigger.Wait(EventTimeout); + task.Wait(); + removeEvent(handler); + + Assert.AreEqual(assertTrue, result, msg); + } + + private static void AssertEvent(string msg, Func action, Action addEvent, Action removeEvent, Func test, bool assertTrue) + { + ManualResetEventSlim trigger = new ManualResetEventSlim(false); + bool result = false; + + EventHandler handler = (s, e) => + { + if (test != null) + { + result |= test(s); + trigger.Set(); + } + else + result = true; + }; + + addEvent(handler); + var task = action(); + trigger.Wait(EventTimeout); + task.Wait(); + removeEvent(handler); + + Assert.AreEqual(assertTrue, result, msg); + } + + private static void WaitAll(params Task[] tasks) + { + Task.WaitAll(tasks); + } + private static void WaitAll(IEnumerable tasks) + { + Task.WaitAll(tasks.ToArray()); + } + private static void WaitMany(params IEnumerable[] tasks) + { + Task.WaitAll(tasks.Where(x => x != null).SelectMany(x => x).ToArray()); + } + + #endregion + } } diff --git a/test/Discord.Net.Tests/packages.config b/test/Discord.Net.Tests/packages.config index 0eaf37a38..2abc396bb 100644 --- a/test/Discord.Net.Tests/packages.config +++ b/test/Discord.Net.Tests/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file