diff --git a/Discord.Net.sln b/Discord.Net.sln index 11960606b0..94259e2a75 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -1,12 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "src\Discord.Net\Discord.Net.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Tests", "test\Discord.Net.Tests\Discord.Net.Tests.xproj", "{69EECB8D-8705-424F-9202-F7F4051EE403}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU + {69EECB8D-8705-424F-9202-F7F4051EE403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69EECB8D-8705-424F-9202-F7F4051EE403}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69EECB8D-8705-424F-9202-F7F4051EE403}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69EECB8D-8705-424F-9202-F7F4051EE403}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/Discord.Net.Tests/Discord.Net.Tests.csproj b/test/Discord.Net.Tests/Discord.Net.Tests.csproj deleted file mode 100644 index 2a50610cc8..0000000000 --- a/test/Discord.Net.Tests/Discord.Net.Tests.csproj +++ /dev/null @@ -1,97 +0,0 @@ - - - - Debug - AnyCPU - {855D6B1D-847B-42DA-BE6A-23683EA89511} - Library - Properties - Discord.Tests - Discord.Net.Tests - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - {c6a50d24-cbd3-4e76-852c-4dca60bbd608} - Discord.Net.Net45 - - - - - - - False - - - False - - - False - - - False - - - - - - - - \ No newline at end of file diff --git a/test/Discord.Net.Tests/Discord.Net.Tests.xproj b/test/Discord.Net.Tests/Discord.Net.Tests.xproj new file mode 100644 index 0000000000..1c291ddb03 --- /dev/null +++ b/test/Discord.Net.Tests/Discord.Net.Tests.xproj @@ -0,0 +1,21 @@ + + + + 14.0.25420 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 69eecb8d-8705-424f-9202-f7f4051ee403 + Discord.Tests + .\obj + .\bin\ + + + 2.0 + + + + + + \ No newline at end of file diff --git a/test/Discord.Net.Tests/Framework/MockRestClient.cs b/test/Discord.Net.Tests/Framework/MockRestClient.cs new file mode 100644 index 0000000000..1203ee5254 --- /dev/null +++ b/test/Discord.Net.Tests/Framework/MockRestClient.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Discord.Net.Rest; +using System.Collections.ObjectModel; + +namespace Discord.Tests.Framework +{ + public class MockRestClient : IRestClient + { + public MockRestClient(string baseUrl) + { + _requestHandler = new RequestHandler(); + } + + private Dictionary _headers = new Dictionary(); + public IReadOnlyDictionary Headers => + new ReadOnlyDictionary(_headers); + private RequestHandler _requestHandler; + + public Task SendAsync(string method, string endpoint, bool headerOnly = false) => + SendAsync(method, endpoint, "", headerOnly); + + public Task SendAsync(string method, string endpoint, IReadOnlyDictionary multipartParams, bool headerOnly = false) + { + throw new NotImplementedException(); + } + + public Task SendAsync(string method, string endpoint, string json, bool headerOnly = false) + { + return Task.FromResult(_requestHandler.GetMock(method, endpoint, json, Headers)); + } + + public void SetCancelToken(CancellationToken cancelToken) { } + + public void SetHeader(string key, string value) + { + if (_headers.ContainsKey(key)) + _headers.Remove(key); + _headers.Add(key, value); + } + } +} diff --git a/test/Discord.Net.Tests/Framework/Mocks/Rest/Guilds.cs b/test/Discord.Net.Tests/Framework/Mocks/Rest/Guilds.cs new file mode 100644 index 0000000000..c95e69b561 --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Mocks/Rest/Guilds.cs @@ -0,0 +1,23 @@ +using Discord.API; + +namespace Discord.Tests.Framework.Mocks.Rest +{ + public static class Guilds + { + public static Guild DiscordApi => new Guild() + { + Id = 81384788765712384, + Name = "Discord API", + OwnerId = 53905483156684800, + MfaLevel = 0, + VerificationLevel = 0, + Roles = new Role[] { Roles.Everyone(81384788765712384), Roles.DiscordEmployee, Roles.LibraryDevs }, + AFKTimeout = 3600, + Region = "us-east", + DefaultMessageNotifications = (DefaultMessageNotifications)1, + EmbedChannelId = 81384788765712384, + EmbedEnabled = true, + Icon = "2aab26934e72b4ec300c5aa6cf67c7b3" + }; + } +} diff --git a/test/Discord.Net.Tests/Framework/Mocks/Rest/Roles.cs b/test/Discord.Net.Tests/Framework/Mocks/Rest/Roles.cs new file mode 100644 index 0000000000..676661eeff --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Mocks/Rest/Roles.cs @@ -0,0 +1,43 @@ +using Discord.API; + +namespace Discord.Tests.Framework.Mocks.Rest +{ + public static class Roles + { + // TODO: These mocks need to include 'mentionable' when the library implements it. + + public static Role Everyone(ulong guildId) => new Role() + { + Id = guildId, + Name = "@everyone", + Color = 0, + Hoist = false, + Permissions = 104324097, + Position = 0, + Managed = false + }; + + public static Role LibraryDevs => new Role() + { + Id = 81793792671232000, + Name = "Library Devs", + Color = 42607, + Hoist = true, + Permissions = 268435456, + Position = 17, + Managed = false + }; + + public static Role DiscordEmployee => new Role() + { + Id = 103548914652696576, + Name = "Discord Employee", + Color = 10181046, + Hoist = false, + Permissions = 29368358, + Position = 20, + Managed = false + }; + + } +} diff --git a/test/Discord.Net.Tests/Framework/Mocks/Rest/Users.cs b/test/Discord.Net.Tests/Framework/Mocks/Rest/Users.cs new file mode 100644 index 0000000000..69bfb26300 --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Mocks/Rest/Users.cs @@ -0,0 +1,38 @@ +using Discord.API; + +namespace Discord.Tests.Framework.Mocks.Rest +{ + public static class Users + { + public static User SelfUser => new User() + { + Id = 103559217914318848, + Username = "Jake", + Discriminator = "0001", + Email = "SelfUser@mocks.foxbot.me", + MfaEnabled = true, + Verified = true, + Avatar = "cdd7ae679ef37ce03e097221c70aeed6" + }; + + public static User BotSelfUser => new User() + { + Id = 145584102551060480, + Username = "foxboat", + Discriminator = "8888", + Email = null, + MfaEnabled = true, + Verified = true, + Avatar = "5f0be46cea584d2225e6c15e8418fb52", + Bot = true + }; + + public static User PublicUser => new User() + { + Id = 66078337084162048, + Username = "foxbot", + Discriminator = "0282", + Avatar = "cdd7ae679ef37ce03e097221c70aeed6" + }; + } +} diff --git a/test/Discord.Net.Tests/Framework/RequestHandler.cs b/test/Discord.Net.Tests/Framework/RequestHandler.cs new file mode 100644 index 0000000000..ad54f3997b --- /dev/null +++ b/test/Discord.Net.Tests/Framework/RequestHandler.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Net; +using System.Text; +using UserRoutes = Discord.Tests.Framework.Routes.Users; +using GuildRoutes = Discord.Tests.Framework.Routes.Guilds; +using Contracts = Discord.Tests.Framework.Routes.Contracts; +using Newtonsoft.Json; +using Discord.Net.Converters; +using Discord.Net; + +namespace Discord.Tests.Framework +{ + public class RequestHandler + { + public delegate object Response(string json, IReadOnlyDictionary requestHeaders); + + internal static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { ContractResolver = new DiscordContractResolver() }; + + internal Dictionary Routes = new Dictionary() + { + // --- USERS + // Get Current User + ["GET users/@me"] = new Response(UserRoutes.Me), + // Get User by ID + ["GET users/66078337084162048"] = new Response(UserRoutes.Public), + // Get User by Tag + ["GET users?q=foxbot%230282&limit=1"] = new Response(UserRoutes.Query), + // --- GUILDS + ["GET guilds/81384788765712384"] = new Response(GuildRoutes.DiscordApi) + }; + + internal Stream GetMock(string method, string endpoint, string json, IReadOnlyDictionary requestHeaders) + { + var key = string.Format("{0} {1}", method.ToUpperInvariant(), endpoint.ToLowerInvariant()); + if (!Routes.ContainsKey(key)) + throw new HttpException(HttpStatusCode.NotFound, $"{key}: {json}"); + Contracts.EnsureAuthorization(requestHeaders); + var model = Routes[key].Invoke(json, requestHeaders); + var textResponse = JsonConvert.SerializeObject(model, SerializerSettings); + return new MemoryStream(Encoding.UTF8.GetBytes(textResponse)); + } + } +} diff --git a/test/Discord.Net.Tests/Framework/Routes/Contracts.cs b/test/Discord.Net.Tests/Framework/Routes/Contracts.cs new file mode 100644 index 0000000000..ceac0df691 --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Routes/Contracts.cs @@ -0,0 +1,24 @@ +using Discord.Net; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; + +namespace Discord.Tests.Framework.Routes +{ + public static class Contracts + { + public static readonly string UserToken = "token.user"; + public static readonly string BotToken = "token.bot"; + public static readonly string BearerToken = "token.bearer"; + + public static void EnsureAuthorization(IReadOnlyDictionary requestHeaders) + { + if (!requestHeaders.ContainsKey("authorization")) throw new HttpException(HttpStatusCode.Forbidden); + if (requestHeaders["authorization"] != UserToken + && requestHeaders["authorization"] != $"Bot {BotToken}" + && requestHeaders["authorization"] != $"Bearer {BearerToken}") throw new HttpException(HttpStatusCode.Forbidden); + } + } +} diff --git a/test/Discord.Net.Tests/Framework/Routes/Guilds.cs b/test/Discord.Net.Tests/Framework/Routes/Guilds.cs new file mode 100644 index 0000000000..69ab8068fa --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Routes/Guilds.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using GuildMocks = Discord.Tests.Framework.Mocks.Rest.Guilds; + +namespace Discord.Tests.Framework.Routes +{ + public static class Guilds + { + public static object DiscordApi(string json, IReadOnlyDictionary requestHeaders) => + GuildMocks.DiscordApi; + } +} diff --git a/test/Discord.Net.Tests/Framework/Routes/Users.cs b/test/Discord.Net.Tests/Framework/Routes/Users.cs new file mode 100644 index 0000000000..271aa3a729 --- /dev/null +++ b/test/Discord.Net.Tests/Framework/Routes/Users.cs @@ -0,0 +1,22 @@ +using UserMocks = Discord.Tests.Framework.Mocks.Rest.Users; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Discord.Tests.Framework.Routes +{ + public static class Users + { + public static object Me(string json, IReadOnlyDictionary requestHeaders) + { + if (requestHeaders["authorization"] == Contracts.UserToken || requestHeaders["authorization"] == $"Bearer {Contracts.BearerToken}") + return UserMocks.SelfUser; + else + return UserMocks.BotSelfUser; + } + + public static object Public(string json, IReadOnlyDictionary requestHeaders) => + UserMocks.PublicUser; + public static object Query(string json, IReadOnlyDictionary requestHeaders) => + ImmutableArray.Create(UserMocks.PublicUser); + } +} diff --git a/test/Discord.Net.Tests/Properties/AssemblyInfo.cs b/test/Discord.Net.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 5b1c7b1252..0000000000 --- a/test/Discord.Net.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Discord.Net.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Discord.Net.Tests")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("855d6b1d-847b-42da-be6a-23683ea89511")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/test/Discord.Net.Tests/Rest/GuildTests.cs b/test/Discord.Net.Tests/Rest/GuildTests.cs new file mode 100644 index 0000000000..bfeef9bab7 --- /dev/null +++ b/test/Discord.Net.Tests/Rest/GuildTests.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; +using Xunit; +using Discord.Rest; +using Contracts = Discord.Tests.Framework.Routes.Contracts; +using Mocks = Discord.Tests.Framework.Mocks.Rest.Guilds; +using RoleMocks = Discord.Tests.Framework.Mocks.Rest.Roles; + +namespace Discord.Tests.Rest +{ + public class GuildTests : IClassFixture + { + public GuildTests(RestFixture fixture) + { + _client = fixture.Client; + _client.LoginAsync(TokenType.Bot, Contracts.BotToken).GetAwaiter().GetResult(); + } + + private DiscordRestClient _client; + + [Fact] + public async Task GetGuild() + { + var guild = await _client.GetGuildAsync(81384788765712384); + Assert.Equal(Mocks.DiscordApi.Id, guild.Id); + Assert.Equal(Mocks.DiscordApi.Name, guild.Name); + Assert.Equal(Mocks.DiscordApi.OwnerId, guild.OwnerId); + Assert.Equal(Mocks.DiscordApi.MfaLevel, guild.MfaLevel); + Assert.Equal(Mocks.DiscordApi.VerificationLevel, guild.VerificationLevel); + Assert.Equal(Mocks.DiscordApi.Roles.Length, guild.Roles.Count); + Assert.Equal(Mocks.DiscordApi.AFKTimeout, guild.AFKTimeout); + Assert.Equal(Mocks.DiscordApi.DefaultMessageNotifications, guild.DefaultMessageNotifications); + Assert.Equal(Mocks.DiscordApi.EmbedChannelId.GetValueOrDefault(), guild.EmbedChannelId); + Assert.Equal(Mocks.DiscordApi.EmbedEnabled, guild.IsEmbeddable); + } + [Fact] + public async Task GetInvalidGuild() + { + var guild = await _client.GetGuildAsync(1); + Assert.Null(guild); + } + } +} diff --git a/test/Discord.Net.Tests/Rest/LoginTests.cs b/test/Discord.Net.Tests/Rest/LoginTests.cs new file mode 100644 index 0000000000..06c442a399 --- /dev/null +++ b/test/Discord.Net.Tests/Rest/LoginTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using Discord; +using Discord.Rest; +using Routes = Discord.Tests.Framework.Routes.Users; +using Contracts = Discord.Tests.Framework.Routes.Contracts; +using Discord.Net; + +namespace Discord.Tests.Rest +{ + public class LoginTests : IClassFixture + { + RestFixture fixture; + + public LoginTests(RestFixture fixture) + { + this.fixture = fixture; + } + + [Fact] + public async Task LoginAsUser() + { + var client = fixture.Client; + await client.LoginAsync(TokenType.User, Contracts.UserToken); + } + [Fact] + public async Task LoginAsUserWithInvalidToken() + { + var client = fixture.Client; + await Assert.ThrowsAsync(async () => await client.LoginAsync(TokenType.User, "token.invalid")); + } + [Fact] + public async Task LoginAsBot() + { + var client = fixture.Client; + await client.LoginAsync(TokenType.Bot, Contracts.BotToken); + } + [Fact] + public async Task LoginAsBotWithInvalidToken() + { + var client = fixture.Client; + await Assert.ThrowsAsync(async () => await client.LoginAsync(TokenType.Bot, "token.invalid")); + } + [Fact] + public async Task LoginAsBearer() + { + var client = fixture.Client; + await client.LoginAsync(TokenType.Bearer, Contracts.BearerToken); + } + [Fact] + public async Task LoginAsBearerWithInvalidToken() + { + var client = fixture.Client; + await Assert.ThrowsAsync(async () => await client.LoginAsync(TokenType.Bearer, "token.invalid")); + } + } +} diff --git a/test/Discord.Net.Tests/Rest/RestFixture.cs b/test/Discord.Net.Tests/Rest/RestFixture.cs new file mode 100644 index 0000000000..7c40bb96e7 --- /dev/null +++ b/test/Discord.Net.Tests/Rest/RestFixture.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Discord.Rest; +using Discord.Net.Rest; +using Discord.Tests.Framework; + +namespace Discord.Tests.Rest +{ + public class RestFixture + { + public DiscordRestClient Client + { + get + { + var Config = new DiscordRestConfig() + { + RestClientProvider = new RestClientProvider(baseUrl => new MockRestClient(baseUrl)) + }; + return new DiscordRestClient(Config); + } + } + } +} diff --git a/test/Discord.Net.Tests/Rest/UserTests.cs b/test/Discord.Net.Tests/Rest/UserTests.cs new file mode 100644 index 0000000000..118294df72 --- /dev/null +++ b/test/Discord.Net.Tests/Rest/UserTests.cs @@ -0,0 +1,60 @@ +using System.Threading.Tasks; +using Xunit; +using Discord.Rest; +using Contracts = Discord.Tests.Framework.Routes.Contracts; +using Mocks = Discord.Tests.Framework.Mocks.Rest.Users; + +namespace Discord.Tests.Rest +{ + public class UserTests : IClassFixture + { + public UserTests(RestFixture fixture) + { + _client = fixture.Client; + _client.LoginAsync(TokenType.Bot, Contracts.BotToken).GetAwaiter().GetResult(); + } + + private DiscordRestClient _client; + + [Fact] + public async Task GetCurrentUser() + { + var user = await _client.GetCurrentUserAsync(); + Assert.Equal(Mocks.BotSelfUser.Id, user.Id); + Assert.Equal(Mocks.BotSelfUser.Username.GetValueOrDefault(), user.Username); + Assert.Equal(Mocks.BotSelfUser.Discriminator.GetValueOrDefault(), user.Discriminator); + Assert.Equal(Mocks.BotSelfUser.Bot.GetValueOrDefault(), user.IsBot); + Assert.Equal(Mocks.BotSelfUser.Email.GetValueOrDefault(), user.Email); + Assert.Equal(Mocks.BotSelfUser.MfaEnabled.GetValueOrDefault(), user.IsMfaEnabled); + Assert.Equal(Mocks.BotSelfUser.Verified.GetValueOrDefault(), user.IsVerified); + } + [Fact] + public async Task GetUserById() + { + var user = await _client.GetUserAsync(66078337084162048); + Assert.Equal(Mocks.PublicUser.Id, user.Id); + Assert.Equal(Mocks.PublicUser.Username.GetValueOrDefault(), user.Username); + Assert.Equal(Mocks.PublicUser.Discriminator.GetValueOrDefault(), user.Discriminator); + } + [Fact] + public async Task GetInvalidUserById() + { + var user = await _client.GetUserAsync(1); + Assert.Null(user); + } + [Fact] + public async Task GetUserByTag() + { + var user = await _client.GetUserAsync("foxbot", "0282"); + Assert.Equal(Mocks.PublicUser.Id, user.Id); + Assert.Equal(Mocks.PublicUser.Username.GetValueOrDefault(), user.Username); + Assert.Equal(Mocks.PublicUser.Discriminator.GetValueOrDefault(), user.Discriminator); + } + [Fact] + public async Task GetInvalidUserByTag() + { + var user = await _client.GetUserAsync("Voltana", "8252"); + Assert.Null(user); + } + } +} diff --git a/test/Discord.Net.Tests/Tests.cs b/test/Discord.Net.Tests/Tests.cs deleted file mode 100644 index d8d09cd3dd..0000000000 --- a/test/Discord.Net.Tests/Tests.cs +++ /dev/null @@ -1,494 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Discord.Tests -{ - //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 - - private static DiscordSocketClient _hostBot, _targetBot, _observerBot; - private static Guild _testGuild; - private static TextChannel _testGuildChannel; - private static Random _random; - private static PublicInvite _testGuildInvite; - - private static TestContext _context; - - private static string _hostToken; - private static string _observerToken; - private static string _targetToken; - - private static string GetRandomText() - { - lock (_random) - return $"test_{_random.Next()}"; - } - - #region Initialization - - [ClassInitialize] - public static void Initialize(TestContext testContext) - { - _context = testContext; - - _hostToken = Environment.GetEnvironmentVariable("discord-unit-host_token"); - _observerToken = Environment.GetEnvironmentVariable("discord-unit-observer_token"); - _targetToken = Environment.GetEnvironmentVariable("discord-unit-target_token"); - } - - [TestMethod] - [Priority(1)] - public async Task TestInitialize() - { - _context.WriteLine("Initializing."); - - _random = new Random(); - - _hostBot = new DiscordSocketClient(_hostToken); - _targetBot = new DiscordSocketClient(_targetToken); - _observerBot = new DiscordSocketClient(_observerToken); - - await _hostBot.Login(); - - await Task.Delay(3000); - - //Cleanup existing Guilds - (await _hostBot.GetGuilds()).Select(x => x.Owner.Id == _hostBot.CurrentUser.Id ? x.Delete() : x.Leave()); - - //Create new Guild and invite the other bots to it - - _testGuild = await _hostBot.CreateGuild("Discord.Net Testing", _hostBot.GetOptimalVoiceRegion()); - - await Task.Delay(1000); - - PublicInvite invite = await _testGuild.CreateInvite(60, 3, false, false); - _testGuildInvite = invite; - - _context.WriteLine($"Host: {_hostBot.CurrentUser.Username} in {(await _hostBot.GetGuilds()).Count()}"); - } - - [TestMethod] - [Priority(2)] - public async Task TestTokenLogin_Ready() - { - AssertEvent( - "READY never received", - async () => await _observerBot.Login(), - x => _observerBot.Connected += x, - x => _observerBot.Connected -= x, - null, - true); - (await _observerBot.GetGuilds()).Select(x => x.Owner.Id == _observerBot.CurrentUser.Id ? x.Delete() : x.Leave()); - await _observerBot.RestClient.Send(new API.Rest.AcceptInviteRequest(_testGuildInvite.Code)); - } - - [TestMethod] - [Priority(2)] - public async Task TestReady() - { - AssertEvent( - "READY never received", - async () => await _targetBot.Login(), - x => _targetBot.Connected += x, - x => _targetBot.Connected -= x, - null, - true); - - (await _targetBot.GetGuilds()).Select(x => x.Owner.Id == _targetBot.CurrentUser.Id ? x.Delete() : x.Leave()); - _testGuildChannel = _testGuild.DefaultChannel; - } - - #endregion - - // Guilds - - #region Guild Tests - - [TestMethod] - [Priority(3)] - public void TestJoinedGuild() - { - AssertEvent( - "Never Got JoinedGuild", - async () => await _targetBot.RestClient.Send(new API.Rest.AcceptInviteRequest(_testGuildInvite.Code)), - x => _targetBot.JoinedGuild += x, - x => _targetBot.JoinedGuild -= x); - } - - #endregion - - #region Channel Tests - - //Channels - [TestMethod] - public void TestCreateTextChannel() - { - GuildChannel channel = null; - string name = GetRandomText(); - AssertEvent( - "ChannelCreated event never received", - async () => channel = await _testGuild.CreateTextChannel(name), - x => _targetBot.ChannelCreated += x, - x => _targetBot.ChannelCreated -= x, - (s, e) => e.Channel.Id == channel.Id); - - AssertEvent( - "ChannelDestroyed event never received", - async () => await channel.Delete(), - x => _targetBot.ChannelDestroyed += x, - x => _targetBot.ChannelDestroyed -= x, - (s, e) => e.Channel.Id == channel.Id); - } - [TestMethod] - public void TestCreateVoiceChannel() - { - GuildChannel channel = null; - string name = GetRandomText(); - AssertEvent( - "ChannelCreated event never received", - async () => channel = await _testGuild.CreateVoiceChannel(name), - x => _targetBot.ChannelCreated += x, - x => _targetBot.ChannelCreated -= x, - (s, e) => e.Channel.Id == channel.Id); - - AssertEvent( - "ChannelDestroyed event never received", - async () => await channel.Delete(), - x => _targetBot.ChannelDestroyed += x, - x => _targetBot.ChannelDestroyed -= x, - (s, e) => e.Channel.Id == channel.Id); - } - - [TestMethod] - [ExpectedException(typeof(Net.HttpException))] - public async Task TestCreateChannel_NoName() - { - await _testGuild.CreateTextChannel($""); - } - [TestMethod] - public async Task Test_CreateGetChannel() - { - var name = GetRandomText(); - var channel = await _testGuild.CreateTextChannel(name); - var get_channel = _testGuild.GetChannel(channel.Id); - Assert.AreEqual(channel.Id, get_channel.Id, "ID of Channel and GetChannel were not equal."); - } - [TestMethod] - public void TestSendTyping() - { - var channel = _testGuildChannel; - AssertEvent( - "UserUpdated event never fired.", - async () => await channel.TriggerTyping(), - x => _targetBot.UserIsTyping += x, - x => _targetBot.UserIsTyping -= x); - } - [TestMethod] - public void TestEditChannel() - { - var channel = _testGuildChannel; - AssertEvent( - "ChannelUpdated Never Received", - async () => await channel.Modify(x => - { - x.Name = GetRandomText(); - x.Topic = $"topic - {GetRandomText()}"; - x.Position = 26; - }), - x => _targetBot.ChannelUpdated += x, - x => _targetBot.ChannelUpdated -= x); - } - [TestMethod] - public void TestChannelMention() - { - var channel = _testGuildChannel; - Assert.AreEqual($"<#{channel.Id}>", channel.Mention, "Generated channel mention was not the expected channel mention."); - } - [TestMethod] - public void TestChannelUserCount() - { - Assert.AreEqual(3, _testGuildChannel.Users.Count(), "Read an incorrect number of users in a channel"); - } - - #endregion - - #region Message Tests - - //Messages - [TestMethod] - public async Task TestMessageEvents() - { - string name = GetRandomText(); - var channel = await _testGuild.CreateTextChannel(name); - _context.WriteLine($"Channel Name: {channel.Name} / {channel.Guild.Name}"); - string text = GetRandomText(); - 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.Modify(x => - { - x.Content = 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() - { - string name = GetRandomText(); - var channel = await _testGuild.CreateTextChannel(name); - for (var i = 0; i < 10; i++) await channel.SendMessage(GetRandomText()); - while (channel.Discord.MessageQueue.Count > 0) await Task.Delay(100); - var messages = await channel.GetMessages(10); - Assert.AreEqual(10, messages.Count(), "Expected 10 messages in downloaded array, did not see 10."); - } - [TestMethod] - public async Task TestSendTTSMessage() - { - var channel = await _testGuild.CreateTextChannel(GetRandomText()); - AssertEvent( - "MessageCreated event never fired", - async () => await channel.SendMessage(GetRandomText(), true), - x => _targetBot.MessageReceived += x, - x => _targetBot.MessageReceived -= x, - (s, e) => e.Message.IsTTS); - } - - #endregion - - #region User Tests - - [TestMethod] - public async Task TestUserMentions() - { - var user = (await _targetBot.GetGuild(_testGuild.Id)).CurrentUser; - Assert.AreEqual($"<@{user.Id}>", user.Mention); - } - [TestMethod] - public void TestUserEdit() - { - var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); - AssertEvent( - "UserUpdated never fired", - async () => await user.Modify(x => - { - x.Deaf = true; - x.Mute = true; - }), - x => _targetBot.UserUpdated += x, - x => _targetBot.UserUpdated -= x); - } - [TestMethod] - public void TestEditSelf() - { - throw new NotImplementedException(); - /*var name = RandomText - AssertEvent( - "UserUpdated never fired", - async () => await _targetBot.CurrentUser.Modify(TargetPassword, name), - x => _obGuildBot.UserUpdated += x, - x => _obGuildBot.UserUpdated -= x, - (s, e) => e.After.Username == 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 Task SetStatus(DiscordClient _client, UserStatus status) - { - throw new NotImplementedException(); - /*_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.CurrentUser.CurrentGame == "test game"); - - } - private Task SetGame(DiscordClient _client, string game) - { - throw new NotImplementedException(); - //_client.SetGame(game); - //await Task.Delay(5); - } - - #endregion - - #region Permission Tests - - // Permissions - [TestMethod] - public async Task Test_AddGet_PermissionsRule() - { - var channel = await _testGuild.CreateTextChannel(GetRandomText()); - var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); - var perms = new OverwritePermissions(sendMessages: PermValue.Deny); - await channel.UpdatePermissionOverwrite(user, perms); - var resultPerms = channel.GetPermissionOverwrite(user); - Assert.IsNotNull(resultPerms, "Perms retrieved from Guild were null."); - } - [TestMethod] - public async Task Test_AddRemove_PermissionsRule() - { - var channel = await _testGuild.CreateTextChannel(GetRandomText()); - var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); - var perms = new OverwritePermissions(sendMessages: PermValue.Deny); - await channel.UpdatePermissionOverwrite(user, perms); - await channel.RemovePermissionOverwrite(user); - await Task.Delay(200); - Assert.AreEqual(PermValue.Inherit, channel.GetPermissionOverwrite(user)?.SendMessages); - } - [TestMethod] - public async Task Test_Permissions_Event() - { - var channel = await _testGuild.CreateTextChannel(GetRandomText()); - var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); - var perms = new OverwritePermissions(sendMessages: PermValue.Deny); - AssertEvent - ("ChannelUpdatedEvent never fired.", - async () => await channel.UpdatePermissionOverwrite(user, perms), - x => _targetBot.ChannelUpdated += x, - x => _targetBot.ChannelUpdated -= x, - (s, e) => e.Channel == channel && (e.After as GuildChannel).PermissionOverwrites.Count() != (e.Before as GuildChannel).PermissionOverwrites.Count()); - } - [TestMethod] - [ExpectedException(typeof(Net.HttpException))] - public async Task Test_Affect_Permissions_Invalid_Channel() - { - var channel = await _testGuild.CreateTextChannel(GetRandomText()); - var user = _testGuild.GetUser(_targetBot.CurrentUser.Id); - var perms = new OverwritePermissions(sendMessages: PermValue.Deny); - await channel.Delete(); - await channel.UpdatePermissionOverwrite(user, perms); - } - - #endregion - - - [ClassCleanup] - public static async Task Cleanup() - { - WaitMany( - (await _hostBot.GetGuilds()).Select(x => x.Owner.Id == _hostBot.CurrentUser.Id ? x.Delete() : x.Leave()), - (await _targetBot.GetGuilds()).Select(x => x.Owner.Id == _targetBot.CurrentUser.Id ? x.Delete() : x.Leave()), - (await _observerBot.GetGuilds()).Select(x => x.Owner.Id == _observerBot.CurrentUser.Id ? x.Delete() : x.Leave())); - - WaitAll( - _hostBot.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 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/config.json.example b/test/Discord.Net.Tests/config.json.example deleted file mode 100644 index 638d65b4d0..0000000000 --- a/test/Discord.Net.Tests/config.json.example +++ /dev/null @@ -1,14 +0,0 @@ -{ - "user1": { - "email": "user1@example.com", - "password": "password123" - }, - "user2": { - "email": "user2@example.com", - "password": "password456" - }, - "user3": { - "email": "user3@example.com", - "password": "password789" - } -} \ No newline at end of file diff --git a/test/Discord.Net.Tests/packages.config b/test/Discord.Net.Tests/packages.config deleted file mode 100644 index 2abc396bbe..0000000000 --- a/test/Discord.Net.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/Discord.Net.Tests/project.json b/test/Discord.Net.Tests/project.json new file mode 100644 index 0000000000..96ab1fec90 --- /dev/null +++ b/test/Discord.Net.Tests/project.json @@ -0,0 +1,27 @@ +{ + "version": "1.0.0-*", + "buildOptions": { + "debugType": "portable" + }, + "dependencies": { + "System.Runtime.Serialization.Primitives": "4.1.1", + "xunit": "2.1.0", + "dotnet-test-xunit": "1.0.0-*", + "Discord.Net": "1.0.0-*" + }, + "testRunner": "xunit", + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + } + }, + "imports": [ + "dotnet5.4", + "portable-net451+win8" + ] + } + } +}