test: Split Unit and Integration tests into separate projects (#1290)
* Squashed commit of test rewrite changes fix missing priority speaker flag rewrite the TestChannelPermissionModify test add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests copy the token utils tests make the mocked entities sealed classes copy the TypeReaderTests class properly dispose the CommandService in the TypeReaderTests start writing tests for EmbedBuilder and related classes test that properties throw ArgumentException when invalid add tests for the embed length property add withFooter tests finish adding tests to EmbedBuilder fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add some tests that show that guild can be modified await async assert add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests make the mocked entities sealed classes properly dispose the CommandService in the TypeReaderTests fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests update the azure CI build script separate execution of test projects so that if one fails the other will not pass one of the unit tests failed, but the analzyer tests passed fix test that would break in different timezones enable the integration tests (only on dev branch) * Squashed commit of test rewrite changes fix missing priority speaker flag rewrite the TestChannelPermissionModify test add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests copy the token utils tests make the mocked entities sealed classes copy the TypeReaderTests class properly dispose the CommandService in the TypeReaderTests start writing tests for EmbedBuilder and related classes test that properties throw ArgumentException when invalid add tests for the embed length property add withFooter tests finish adding tests to EmbedBuilder fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add some tests that show that guild can be modified await async assert add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests make the mocked entities sealed classes properly dispose the CommandService in the TypeReaderTests fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests update the azure CI build script separate execution of test projects so that if one fails the other will not pass one of the unit tests failed, but the analzyer tests passed fix test that would break in different timezones enable the integration tests (only on dev branch) * Update mocked channels for changed SendFileAsync signature * comment out the integration tests from the build script no bot token is provided to this script, and use of integration tests in CI is questionable here * force rebuild because Azure linux build broke
This commit is contained in:
committed by
Christopher F
parent
40844b9e13
commit
a797be9ca0
223
test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs
Normal file
223
test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.ChannelPermissions"/> type and related functions.
|
||||
/// </summary>
|
||||
public class ChannelPermissionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the default value of the <see cref="Discord.ChannelPermissions"/> constructor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DefaultConstructor()
|
||||
{
|
||||
var permission = new ChannelPermissions();
|
||||
Assert.Equal((ulong)0, permission.RawValue);
|
||||
Assert.Equal(ChannelPermissions.None.RawValue, permission.RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.ChannelPermission"/> raw value constructor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void RawValueConstructor()
|
||||
{
|
||||
// returns all of the values that will be tested
|
||||
// a Theory cannot be used here, because these values are not all constants
|
||||
IEnumerable<ulong> GetTestValues()
|
||||
{
|
||||
yield return 0;
|
||||
yield return ChannelPermissions.Category.RawValue;
|
||||
yield return ChannelPermissions.DM.RawValue;
|
||||
yield return ChannelPermissions.Group.RawValue;
|
||||
yield return ChannelPermissions.None.RawValue;
|
||||
yield return ChannelPermissions.Text.RawValue;
|
||||
yield return ChannelPermissions.Voice.RawValue;
|
||||
};
|
||||
|
||||
foreach (var rawValue in GetTestValues())
|
||||
{
|
||||
var p = new ChannelPermissions(rawValue);
|
||||
Assert.Equal(rawValue, p.RawValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.ChannelPermissions"/> constructor for each
|
||||
/// of it's flags.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void FlagsConstructor()
|
||||
{
|
||||
// util method for asserting that the constructor sets the given flag
|
||||
void AssertFlag(Func<ChannelPermissions> cstr, ChannelPermission flag)
|
||||
{
|
||||
var p = cstr();
|
||||
// ensure that this flag is set to true
|
||||
Assert.True(p.Has(flag));
|
||||
// ensure that only this flag is set
|
||||
Assert.Equal((ulong)flag, p.RawValue);
|
||||
}
|
||||
|
||||
AssertFlag(() => new ChannelPermissions(createInstantInvite: true), ChannelPermission.CreateInstantInvite);
|
||||
AssertFlag(() => new ChannelPermissions(manageChannel: true), ChannelPermission.ManageChannels);
|
||||
AssertFlag(() => new ChannelPermissions(addReactions: true), ChannelPermission.AddReactions);
|
||||
AssertFlag(() => new ChannelPermissions(viewChannel: true), ChannelPermission.ViewChannel);
|
||||
AssertFlag(() => new ChannelPermissions(sendMessages: true), ChannelPermission.SendMessages);
|
||||
AssertFlag(() => new ChannelPermissions(sendTTSMessages: true), ChannelPermission.SendTTSMessages);
|
||||
AssertFlag(() => new ChannelPermissions(manageMessages: true), ChannelPermission.ManageMessages);
|
||||
AssertFlag(() => new ChannelPermissions(embedLinks: true), ChannelPermission.EmbedLinks);
|
||||
AssertFlag(() => new ChannelPermissions(attachFiles: true), ChannelPermission.AttachFiles);
|
||||
AssertFlag(() => new ChannelPermissions(readMessageHistory: true), ChannelPermission.ReadMessageHistory);
|
||||
AssertFlag(() => new ChannelPermissions(mentionEveryone: true), ChannelPermission.MentionEveryone);
|
||||
AssertFlag(() => new ChannelPermissions(useExternalEmojis: true), ChannelPermission.UseExternalEmojis);
|
||||
AssertFlag(() => new ChannelPermissions(connect: true), ChannelPermission.Connect);
|
||||
AssertFlag(() => new ChannelPermissions(speak: true), ChannelPermission.Speak);
|
||||
AssertFlag(() => new ChannelPermissions(muteMembers: true), ChannelPermission.MuteMembers);
|
||||
AssertFlag(() => new ChannelPermissions(deafenMembers: true), ChannelPermission.DeafenMembers);
|
||||
AssertFlag(() => new ChannelPermissions(moveMembers: true), ChannelPermission.MoveMembers);
|
||||
AssertFlag(() => new ChannelPermissions(useVoiceActivation: true), ChannelPermission.UseVAD);
|
||||
AssertFlag(() => new ChannelPermissions(prioritySpeaker: true), ChannelPermission.PrioritySpeaker);
|
||||
AssertFlag(() => new ChannelPermissions(manageRoles: true), ChannelPermission.ManageRoles);
|
||||
AssertFlag(() => new ChannelPermissions(manageWebhooks: true), ChannelPermission.ManageWebhooks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="Discord.ChannelPermissions.Modify(bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?)"/>
|
||||
/// with each of the parameters.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Modify()
|
||||
{
|
||||
// asserts that a channel permission flag value can be checked
|
||||
// and that modify can set and unset each flag
|
||||
// and that ToList performs as expected
|
||||
void AssertUtil(ChannelPermission permission,
|
||||
Func<ChannelPermissions, bool> has,
|
||||
Func<ChannelPermissions, bool, ChannelPermissions> modify)
|
||||
{
|
||||
var perm = new ChannelPermissions();
|
||||
// ensure permission initially false
|
||||
// use both the function and Has to ensure that the GetPermission
|
||||
// function is working
|
||||
Assert.False(has(perm));
|
||||
Assert.False(perm.Has(permission));
|
||||
|
||||
// enable it, and ensure that it gets set
|
||||
perm = modify(perm, true);
|
||||
Assert.True(has(perm));
|
||||
Assert.True(perm.Has(permission));
|
||||
|
||||
// check ToList behavior
|
||||
var list = perm.ToList();
|
||||
Assert.Contains(permission, list);
|
||||
Assert.Single(list);
|
||||
|
||||
// set it false again
|
||||
perm = modify(perm, false);
|
||||
Assert.False(has(perm));
|
||||
Assert.False(perm.Has(permission));
|
||||
|
||||
// ensure that no perms are set now
|
||||
Assert.Equal(ChannelPermissions.None.RawValue, perm.RawValue);
|
||||
}
|
||||
|
||||
AssertUtil(ChannelPermission.CreateInstantInvite, x => x.CreateInstantInvite, (p, enable) => p.Modify(createInstantInvite: enable));
|
||||
AssertUtil(ChannelPermission.ManageChannels, x => x.ManageChannel, (p, enable) => p.Modify(manageChannel: enable));
|
||||
AssertUtil(ChannelPermission.AddReactions, x => x.AddReactions, (p, enable) => p.Modify(addReactions: enable));
|
||||
AssertUtil(ChannelPermission.ViewChannel, x => x.ViewChannel, (p, enable) => p.Modify(viewChannel: enable));
|
||||
AssertUtil(ChannelPermission.SendMessages, x => x.SendMessages, (p, enable) => p.Modify(sendMessages: enable));
|
||||
AssertUtil(ChannelPermission.SendTTSMessages, x => x.SendTTSMessages, (p, enable) => p.Modify(sendTTSMessages: enable));
|
||||
AssertUtil(ChannelPermission.ManageMessages, x => x.ManageMessages, (p, enable) => p.Modify(manageMessages: enable));
|
||||
AssertUtil(ChannelPermission.EmbedLinks, x => x.EmbedLinks, (p, enable) => p.Modify(embedLinks: enable));
|
||||
AssertUtil(ChannelPermission.AttachFiles, x => x.AttachFiles, (p, enable) => p.Modify(attachFiles: enable));
|
||||
AssertUtil(ChannelPermission.ReadMessageHistory, x => x.ReadMessageHistory, (p, enable) => p.Modify(readMessageHistory: enable));
|
||||
AssertUtil(ChannelPermission.MentionEveryone, x => x.MentionEveryone, (p, enable) => p.Modify(mentionEveryone: enable));
|
||||
AssertUtil(ChannelPermission.UseExternalEmojis, x => x.UseExternalEmojis, (p, enable) => p.Modify(useExternalEmojis: enable));
|
||||
AssertUtil(ChannelPermission.Connect, x => x.Connect, (p, enable) => p.Modify(connect: enable));
|
||||
AssertUtil(ChannelPermission.Speak, x => x.Speak, (p, enable) => p.Modify(speak: enable));
|
||||
AssertUtil(ChannelPermission.MuteMembers, x => x.MuteMembers, (p, enable) => p.Modify(muteMembers: enable));
|
||||
AssertUtil(ChannelPermission.DeafenMembers, x => x.DeafenMembers, (p, enable) => p.Modify(deafenMembers: enable));
|
||||
AssertUtil(ChannelPermission.MoveMembers, x => x.MoveMembers, (p, enable) => p.Modify(moveMembers: enable));
|
||||
AssertUtil(ChannelPermission.UseVAD, x => x.UseVAD, (p, enable) => p.Modify(useVoiceActivation: enable));
|
||||
AssertUtil(ChannelPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
|
||||
AssertUtil(ChannelPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
|
||||
AssertUtil(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for a null channel will throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Null()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
ChannelPermissions.All(null);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="ITextChannel"/> will return a value
|
||||
/// equivalent to <see cref="ChannelPermissions.Text"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Text()
|
||||
{
|
||||
Assert.Equal(ChannelPermissions.Text.RawValue, ChannelPermissions.All(new MockedTextChannel()).RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IVoiceChannel"/> will return a value
|
||||
/// equivalent to <see cref="ChannelPermissions.Voice"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Voice()
|
||||
{
|
||||
Assert.Equal(ChannelPermissions.Voice.RawValue, ChannelPermissions.All(new MockedVoiceChannel()).RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="ICategoryChannel"/> will return a value
|
||||
/// equivalent to <see cref="ChannelPermissions.Category"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Category()
|
||||
{
|
||||
Assert.Equal(ChannelPermissions.Category.RawValue, ChannelPermissions.All(new MockedCategoryChannel()).RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IDMChannel"/> will return a value
|
||||
/// equivalent to <see cref="ChannelPermissions.DM"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_DM()
|
||||
{
|
||||
Assert.Equal(ChannelPermissions.DM.RawValue, ChannelPermissions.All(new MockedDMChannel()).RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IGroupChannel"/> will return a value
|
||||
/// equivalent to <see cref="ChannelPermissions.Group"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Group()
|
||||
{
|
||||
Assert.Equal(ChannelPermissions.Group.RawValue, ChannelPermissions.All(new MockedGroupChannel()).RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an invalid channel will throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChannelTypeResolution_Invalid()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => ChannelPermissions.All(new MockedInvalidChannel()));
|
||||
}
|
||||
}
|
||||
}
|
||||
92
test/Discord.Net.Tests.Unit/ColorTests.cs
Normal file
92
test/Discord.Net.Tests.Unit/ColorTests.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="Discord.Color"/> type.
|
||||
/// </summary>
|
||||
public class ColorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Color_New()
|
||||
{
|
||||
Assert.Equal(0u, new Color().RawValue);
|
||||
Assert.Equal(uint.MinValue, new Color(uint.MinValue).RawValue);
|
||||
Assert.Equal(uint.MaxValue, new Color(uint.MaxValue).RawValue);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_Default()
|
||||
{
|
||||
Assert.Equal(0u, Color.Default.RawValue);
|
||||
Assert.Equal(0, Color.Default.R);
|
||||
Assert.Equal(0, Color.Default.G);
|
||||
Assert.Equal(0, Color.Default.B);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_FromRgb_Byte()
|
||||
{
|
||||
Assert.Equal(0xFF0000u, new Color((byte)255, (byte)0, (byte)0).RawValue);
|
||||
Assert.Equal(0x00FF00u, new Color((byte)0, (byte)255, (byte)0).RawValue);
|
||||
Assert.Equal(0x0000FFu, new Color((byte)0, (byte)0, (byte)255).RawValue);
|
||||
Assert.Equal(0xFFFFFFu, new Color((byte)255, (byte)255, (byte)255).RawValue);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_FromRgb_Int()
|
||||
{
|
||||
Assert.Equal(0xFF0000u, new Color(255, 0, 0).RawValue);
|
||||
Assert.Equal(0x00FF00u, new Color(0, 255, 0).RawValue);
|
||||
Assert.Equal(0x0000FFu, new Color(0, 0, 255).RawValue);
|
||||
Assert.Equal(0xFFFFFFu, new Color(255, 255, 255).RawValue);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_FromRgb_Int_OutOfRange()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>("r", () => new Color(-1024, 0, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("r", () => new Color(1024, 0, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("g", () => new Color(0, -1024, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("g", () => new Color(0, 1024, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("b", () => new Color(0, 0, -1024));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("b", () => new Color(0, 0, 1024));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(-1024, -1024, -1024));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(1024, 1024, 1024));
|
||||
}
|
||||
[Fact]
|
||||
public void Color_FromRgb_Float()
|
||||
{
|
||||
Assert.Equal(0xFF0000u, new Color(1.0f, 0, 0).RawValue);
|
||||
Assert.Equal(0x00FF00u, new Color(0, 1.0f, 0).RawValue);
|
||||
Assert.Equal(0x0000FFu, new Color(0, 0, 1.0f).RawValue);
|
||||
Assert.Equal(0xFFFFFFu, new Color(1.0f, 1.0f, 1.0f).RawValue);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_FromRgb_Float_OutOfRange()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>("r", () => new Color(-2.0f, 0, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("r", () => new Color(2.0f, 0, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("g", () => new Color(0, -2.0f, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("g", () => new Color(0, 2.0f, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("b", () => new Color(0, 0, -2.0f));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("b", () => new Color(0, 0, 2.0f));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(-2.0f, -2.0f, -2.0f));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(2.0f, 2.0f, 2.0f));
|
||||
}
|
||||
[Fact]
|
||||
public void Color_Red()
|
||||
{
|
||||
Assert.Equal(0xAF, new Color(0xAF1390).R);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_Green()
|
||||
{
|
||||
Assert.Equal(0x13, new Color(0xAF1390).G);
|
||||
}
|
||||
[Fact]
|
||||
public void Color_Blue()
|
||||
{
|
||||
Assert.Equal(0x90, new Color(0xAF1390).B);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj
Normal file
21
test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
|
||||
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
|
||||
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />
|
||||
<ProjectReference Include="../../src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj" />
|
||||
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
467
test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs
Normal file
467
test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs
Normal file
@@ -0,0 +1,467 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the <see cref="Discord.EmbedBuilder"/> class.
|
||||
/// </summary>
|
||||
public class EmbedBuilderTests
|
||||
{
|
||||
private const string name = "chrisj";
|
||||
private const string icon = "https://meowpuffygottem.fun/blob.png";
|
||||
private const string url = "https://meowpuffygottem.fun/";
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(string, string, string)"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithAuthor_Strings()
|
||||
{
|
||||
var builder = new EmbedBuilder();
|
||||
// null by default
|
||||
Assert.Null(builder.Author);
|
||||
|
||||
builder = new EmbedBuilder()
|
||||
.WithAuthor(name, icon, url);
|
||||
|
||||
Assert.NotNull(builder.Author);
|
||||
Assert.Equal(name, builder.Author.Name);
|
||||
Assert.Equal(icon, builder.Author.IconUrl);
|
||||
Assert.Equal(url, builder.Author.Url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(EmbedAuthorBuilder)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithAuthor_AuthorBuilder()
|
||||
{
|
||||
var author = new EmbedAuthorBuilder()
|
||||
.WithIconUrl(icon)
|
||||
.WithName(name)
|
||||
.WithUrl(url);
|
||||
var builder = new EmbedBuilder()
|
||||
.WithAuthor(author);
|
||||
Assert.NotNull(builder.Author);
|
||||
Assert.Equal(name, builder.Author.Name);
|
||||
Assert.Equal(icon, builder.Author.IconUrl);
|
||||
Assert.Equal(url, builder.Author.Url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(Action{EmbedAuthorBuilder})"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithAuthor_ActionAuthorBuilder()
|
||||
{
|
||||
var builder = new EmbedBuilder()
|
||||
.WithAuthor((author) =>
|
||||
author.WithIconUrl(icon)
|
||||
.WithName(name)
|
||||
.WithUrl(url));
|
||||
Assert.NotNull(builder.Author);
|
||||
Assert.Equal(name, builder.Author.Name);
|
||||
Assert.Equal(icon, builder.Author.IconUrl);
|
||||
Assert.Equal(url, builder.Author.Url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedAuthorBuilder"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void EmbedAuthorBuilder()
|
||||
{
|
||||
var builder = new EmbedAuthorBuilder()
|
||||
.WithIconUrl(icon)
|
||||
.WithName(name)
|
||||
.WithUrl(url);
|
||||
Assert.Equal(icon, builder.IconUrl);
|
||||
Assert.Equal(name, builder.Name);
|
||||
Assert.Equal(url, builder.Url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that invalid titles throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
/// <param name="title">The embed title to set.</param>
|
||||
[Theory]
|
||||
// 257 chars
|
||||
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKVa")]
|
||||
// 257 chars of whitespace
|
||||
[InlineData(" ")]
|
||||
public void Title_Invalid(string title)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var builder = new EmbedBuilder();
|
||||
builder.Title = title;
|
||||
});
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
new EmbedBuilder().WithTitle(title);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that valid titles do not throw any exceptions.
|
||||
/// </summary>
|
||||
/// <param name="title">The embed title to set.</param>
|
||||
[Theory]
|
||||
// 256 chars
|
||||
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKV")]
|
||||
public void Tile_Valid(string title)
|
||||
{
|
||||
var builder = new EmbedBuilder();
|
||||
builder.Title = title;
|
||||
new EmbedBuilder().WithTitle(title);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that invalid descriptions throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Description_Invalid()
|
||||
{
|
||||
IEnumerable<string> GetInvalid()
|
||||
{
|
||||
yield return new string('a', 2049);
|
||||
}
|
||||
foreach (var description in GetInvalid())
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new EmbedBuilder().WithDescription(description));
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var b = new EmbedBuilder();
|
||||
b.Description = description;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that valid descriptions do not throw any exceptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Description_Valid()
|
||||
{
|
||||
IEnumerable<string> GetValid()
|
||||
{
|
||||
yield return string.Empty;
|
||||
yield return null;
|
||||
yield return new string('a', 2048);
|
||||
}
|
||||
foreach (var description in GetValid())
|
||||
{
|
||||
var b = new EmbedBuilder().WithDescription(description);
|
||||
Assert.Equal(description, b.Description);
|
||||
|
||||
b = new EmbedBuilder();
|
||||
b.Description = description;
|
||||
Assert.Equal(description, b.Description);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that valid urls do not throw any exceptions.
|
||||
/// </summary>
|
||||
/// <param name="url">The url to set.</param>
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData("https://docs.stillu.cc")]
|
||||
public void Url_Valid(string url)
|
||||
{
|
||||
// does not throw an exception
|
||||
var result = new EmbedBuilder()
|
||||
.WithUrl(url)
|
||||
.WithImageUrl(url)
|
||||
.WithThumbnailUrl(url);
|
||||
Assert.Equal(result.Url, url);
|
||||
Assert.Equal(result.ImageUrl, url);
|
||||
Assert.Equal(result.ThumbnailUrl, url);
|
||||
|
||||
result = new EmbedBuilder();
|
||||
result.Url = url;
|
||||
result.ImageUrl = url;
|
||||
result.ThumbnailUrl = url;
|
||||
Assert.Equal(result.Url, url);
|
||||
Assert.Equal(result.ImageUrl, url);
|
||||
Assert.Equal(result.ThumbnailUrl, url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that invalid urls throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
/// <param name="url">The url to set.</param>
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData("not a url")]
|
||||
public void Url_Invalid(string url)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> new EmbedBuilder()
|
||||
.WithUrl(url));
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> new EmbedBuilder()
|
||||
.WithImageUrl(url));
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> new EmbedBuilder()
|
||||
.WithThumbnailUrl(url));
|
||||
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var b = new EmbedBuilder();
|
||||
b.Url = url;
|
||||
});
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var b = new EmbedBuilder();
|
||||
b.ImageUrl = url;
|
||||
});
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var b = new EmbedBuilder();
|
||||
b.ThumbnailUrl = url;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the value of the <see cref="EmbedBuilder.Length"/> property when there are no fields set.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Length_Empty()
|
||||
{
|
||||
var empty = new EmbedBuilder();
|
||||
Assert.Equal(0, empty.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the value of the <see cref="EmbedBuilder.Length"/> property when all fields are set.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Length()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.WithAuthor(name, icon, url)
|
||||
.WithColor(Color.Blue)
|
||||
.WithDescription("This is the test description.")
|
||||
.WithFooter("This is the footer", url)
|
||||
.WithImageUrl(url)
|
||||
.WithThumbnailUrl(url)
|
||||
.WithTimestamp(DateTime.MinValue)
|
||||
.WithTitle("This is the title")
|
||||
.WithUrl(url)
|
||||
.AddField("Field 1", "Inline", true)
|
||||
.AddField("Field 2", "Not Inline", false);
|
||||
Assert.Equal(100, e.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithCurrentTimestamp"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithCurrentTimestamp()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.WithCurrentTimestamp();
|
||||
// ensure within a second of accuracy
|
||||
Assert.Equal(DateTime.UtcNow, e.Timestamp.Value.UtcDateTime, TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithColor(Color)"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithColor()
|
||||
{
|
||||
// use WithColor
|
||||
var e = new EmbedBuilder().WithColor(Color.Red);
|
||||
Assert.Equal(Color.Red.RawValue, e.Color.Value.RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(Action{EmbedFooterBuilder})"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithFooter_ActionFooterBuilder()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.WithFooter(x =>
|
||||
{
|
||||
x.IconUrl = url;
|
||||
x.Text = name;
|
||||
});
|
||||
Assert.Equal(url, e.Footer.IconUrl);
|
||||
Assert.Equal(name, e.Footer.Text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(EmbedFooterBuilder)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithFooter_FooterBuilder()
|
||||
{
|
||||
var footer = new EmbedFooterBuilder()
|
||||
{
|
||||
IconUrl = url,
|
||||
Text = name
|
||||
};
|
||||
var e = new EmbedBuilder()
|
||||
.WithFooter(footer);
|
||||
Assert.Equal(url, e.Footer.IconUrl);
|
||||
Assert.Equal(name, e.Footer.Text);
|
||||
// use the property
|
||||
e = new EmbedBuilder();
|
||||
e.Footer = footer;
|
||||
Assert.Equal(url, e.Footer.IconUrl);
|
||||
Assert.Equal(name, e.Footer.Text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(string, string)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void WithFooter_Strings()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.WithFooter(name, url);
|
||||
Assert.Equal(url, e.Footer.IconUrl);
|
||||
Assert.Equal(name, e.Footer.Text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="EmbedFooterBuilder"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void EmbedFooterBuilder()
|
||||
{
|
||||
var footer = new EmbedFooterBuilder()
|
||||
.WithIconUrl(url)
|
||||
.WithText(name);
|
||||
Assert.Equal(url, footer.IconUrl);
|
||||
Assert.Equal(name, footer.Text);
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests that invalid URLs throw an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void EmbedFooterBuilder_InvalidURL()
|
||||
{
|
||||
IEnumerable<string> InvalidUrls()
|
||||
{
|
||||
yield return "not a url";
|
||||
}
|
||||
foreach (var url in InvalidUrls())
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
new EmbedFooterBuilder().WithIconUrl(url);
|
||||
});
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests that invalid text throws an <see cref="ArgumentException"/>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void EmbedFooterBuilder_InvalidText()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
new EmbedFooterBuilder().WithText(new string('a', 2049));
|
||||
});
|
||||
}
|
||||
[Fact]
|
||||
public void AddField_Strings()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.AddField("name", "value", true);
|
||||
Assert.Equal("name", e.Fields[0].Name);
|
||||
Assert.Equal("value", e.Fields[0].Value);
|
||||
Assert.True(e.Fields[0].IsInline);
|
||||
}
|
||||
[Fact]
|
||||
public void AddField_EmbedFieldBuilder()
|
||||
{
|
||||
var field = new EmbedFieldBuilder()
|
||||
.WithIsInline(true)
|
||||
.WithValue("value")
|
||||
.WithName("name");
|
||||
var e = new EmbedBuilder()
|
||||
.AddField(field);
|
||||
Assert.Equal("name", e.Fields[0].Name);
|
||||
Assert.Equal("value", e.Fields[0].Value);
|
||||
Assert.True(e.Fields[0].IsInline);
|
||||
}
|
||||
[Fact]
|
||||
public void AddField_ActionEmbedFieldBuilder()
|
||||
{
|
||||
var e = new EmbedBuilder()
|
||||
.AddField(x => x
|
||||
.WithName("name")
|
||||
.WithValue("value")
|
||||
.WithIsInline(true));
|
||||
Assert.Equal("name", e.Fields[0].Name);
|
||||
Assert.Equal("value", e.Fields[0].Value);
|
||||
Assert.True(e.Fields[0].IsInline);
|
||||
}
|
||||
[Fact]
|
||||
public void AddField_TooManyFields()
|
||||
{
|
||||
var e = new EmbedBuilder();
|
||||
for (var i = 0; i < 25; i++)
|
||||
{
|
||||
e = e.AddField("name", "value", false);
|
||||
}
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
e = e.AddField("name", "value", false);
|
||||
});
|
||||
}
|
||||
[Fact]
|
||||
public void EmbedFieldBuilder()
|
||||
{
|
||||
var e = new EmbedFieldBuilder()
|
||||
.WithIsInline(true)
|
||||
.WithName("name")
|
||||
.WithValue("value");
|
||||
Assert.Equal("name", e.Name);
|
||||
Assert.Equal("value", e.Value);
|
||||
Assert.True(e.IsInline);
|
||||
// use the properties
|
||||
e = new EmbedFieldBuilder();
|
||||
e.IsInline = true;
|
||||
e.Name = "name";
|
||||
e.Value = "value";
|
||||
Assert.Equal("name", e.Name);
|
||||
Assert.Equal("value", e.Value);
|
||||
Assert.True(e.IsInline);
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData(null)]
|
||||
// 257 chars
|
||||
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKVa")]
|
||||
// 257 chars of whitespace
|
||||
[InlineData(" ")]
|
||||
public void EmbedFieldBuilder_InvalidName(string name)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new EmbedFieldBuilder().WithName(name));
|
||||
}
|
||||
[Fact]
|
||||
public void EmbedFieldBuilder_InvalidValue()
|
||||
{
|
||||
IEnumerable<string> GetInvalidValue()
|
||||
{
|
||||
yield return null;
|
||||
yield return string.Empty;
|
||||
yield return " ";
|
||||
yield return new string('a', 1025);
|
||||
};
|
||||
foreach (var v in GetInvalidValue())
|
||||
Assert.Throws<ArgumentException>(() => new EmbedFieldBuilder().WithValue(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
47
test/Discord.Net.Tests.Unit/EmoteTests.cs
Normal file
47
test/Discord.Net.Tests.Unit/EmoteTests.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class EmoteTests
|
||||
{
|
||||
[Fact]
|
||||
public void Test_Emote_Parse()
|
||||
{
|
||||
Assert.True(Emote.TryParse("<:typingstatus:394207658351263745>", out Emote emote));
|
||||
Assert.NotNull(emote);
|
||||
Assert.Equal("typingstatus", emote.Name);
|
||||
Assert.Equal(394207658351263745UL, emote.Id);
|
||||
Assert.False(emote.Animated);
|
||||
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt);
|
||||
Assert.EndsWith("png", emote.Url);
|
||||
}
|
||||
[Fact]
|
||||
public void Test_Invalid_Emote_Parse()
|
||||
{
|
||||
Assert.False(Emote.TryParse("invalid", out _));
|
||||
Assert.False(Emote.TryParse("<:typingstatus:not_a_number>", out _));
|
||||
Assert.Throws<ArgumentException>(() => Emote.Parse("invalid"));
|
||||
}
|
||||
[Fact]
|
||||
public void Test_Animated_Emote_Parse()
|
||||
{
|
||||
Assert.True(Emote.TryParse("<a:typingstatus:394207658351263745>", out Emote emote));
|
||||
Assert.NotNull(emote);
|
||||
Assert.Equal("typingstatus", emote.Name);
|
||||
Assert.Equal(394207658351263745UL, emote.Id);
|
||||
Assert.True(emote.Animated);
|
||||
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt);
|
||||
Assert.EndsWith("gif", emote.Url);
|
||||
}
|
||||
[Fact]
|
||||
public void Test_Invalid_Amimated_Emote_Parse()
|
||||
{
|
||||
Assert.False(Emote.TryParse("<x:typingstatus:394207658351263745>", out _));
|
||||
Assert.False(Emote.TryParse("<a:typingstatus>", out _));
|
||||
Assert.False(Emote.TryParse("<a:typingstatus:not_a_number>", out _));
|
||||
}
|
||||
}
|
||||
}
|
||||
32
test/Discord.Net.Tests.Unit/FormatTests.cs
Normal file
32
test/Discord.Net.Tests.Unit/FormatTests.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class FormatTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("@everyone", "@everyone")]
|
||||
[InlineData(@"\", @"\\")]
|
||||
[InlineData(@"*text*", @"\*text\*")]
|
||||
[InlineData(@"~text~", @"\~text\~")]
|
||||
[InlineData(@"`text`", @"\`text\`")]
|
||||
[InlineData(@"_text_", @"\_text\_")]
|
||||
public void Sanitize(string input, string expected)
|
||||
{
|
||||
Assert.Equal(expected, Format.Sanitize(input));
|
||||
}
|
||||
[Fact]
|
||||
public void Code()
|
||||
{
|
||||
// no language
|
||||
Assert.Equal("`test`", Format.Code("test"));
|
||||
Assert.Equal("```\nanother\none\n```", Format.Code("another\none"));
|
||||
// language specified
|
||||
Assert.Equal("```cs\ntest\n```", Format.Code("test", "cs"));
|
||||
Assert.Equal("```cs\nanother\none\n```", Format.Code("another\none", "cs"));
|
||||
}
|
||||
}
|
||||
}
|
||||
164
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
Normal file
164
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> type and related functions.
|
||||
/// </summary>
|
||||
public class GuildPermissionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the default value of the <see cref="Discord.GuildPermissions"/> constructor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DefaultConstructor()
|
||||
{
|
||||
var p = new GuildPermissions();
|
||||
Assert.Equal((ulong)0, p.RawValue);
|
||||
Assert.Equal(GuildPermissions.None.RawValue, p.RawValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> raw value constructor.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void RawValueConstructor()
|
||||
{
|
||||
// returns all of the values that will be tested
|
||||
// a Theory cannot be used here, because these values are not all constants
|
||||
IEnumerable<ulong> GetTestValues()
|
||||
{
|
||||
yield return 0;
|
||||
yield return GuildPermissions.None.RawValue;
|
||||
yield return GuildPermissions.All.RawValue;
|
||||
yield return GuildPermissions.Webhook.RawValue;
|
||||
};
|
||||
|
||||
foreach (var rawValue in GetTestValues())
|
||||
{
|
||||
var p = new GuildPermissions(rawValue);
|
||||
Assert.Equal(rawValue, p.RawValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> constructor for each
|
||||
/// of it's flags.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void FlagsConstructor()
|
||||
{
|
||||
// util method for asserting that the constructor sets the given flag
|
||||
void AssertFlag(Func<GuildPermissions> cstr, GuildPermission flag)
|
||||
{
|
||||
var p = cstr();
|
||||
// ensure flag set to true
|
||||
Assert.True(p.Has(flag));
|
||||
// ensure only this flag is set
|
||||
Assert.Equal((ulong)flag, p.RawValue);
|
||||
}
|
||||
|
||||
AssertFlag(() => new GuildPermissions(createInstantInvite: true), GuildPermission.CreateInstantInvite);
|
||||
AssertFlag(() => new GuildPermissions(kickMembers: true), GuildPermission.KickMembers);
|
||||
AssertFlag(() => new GuildPermissions(banMembers: true), GuildPermission.BanMembers);
|
||||
AssertFlag(() => new GuildPermissions(administrator: true), GuildPermission.Administrator);
|
||||
AssertFlag(() => new GuildPermissions(manageChannels: true), GuildPermission.ManageChannels);
|
||||
AssertFlag(() => new GuildPermissions(manageGuild: true), GuildPermission.ManageGuild);
|
||||
AssertFlag(() => new GuildPermissions(addReactions: true), GuildPermission.AddReactions);
|
||||
AssertFlag(() => new GuildPermissions(viewAuditLog: true), GuildPermission.ViewAuditLog);
|
||||
AssertFlag(() => new GuildPermissions(viewChannel: true), GuildPermission.ViewChannel);
|
||||
AssertFlag(() => new GuildPermissions(sendMessages: true), GuildPermission.SendMessages);
|
||||
AssertFlag(() => new GuildPermissions(sendTTSMessages: true), GuildPermission.SendTTSMessages);
|
||||
AssertFlag(() => new GuildPermissions(manageMessages: true), GuildPermission.ManageMessages);
|
||||
AssertFlag(() => new GuildPermissions(embedLinks: true), GuildPermission.EmbedLinks);
|
||||
AssertFlag(() => new GuildPermissions(attachFiles: true), GuildPermission.AttachFiles);
|
||||
AssertFlag(() => new GuildPermissions(readMessageHistory: true), GuildPermission.ReadMessageHistory);
|
||||
AssertFlag(() => new GuildPermissions(mentionEveryone: true), GuildPermission.MentionEveryone);
|
||||
AssertFlag(() => new GuildPermissions(useExternalEmojis: true), GuildPermission.UseExternalEmojis);
|
||||
AssertFlag(() => new GuildPermissions(connect: true), GuildPermission.Connect);
|
||||
AssertFlag(() => new GuildPermissions(speak: true), GuildPermission.Speak);
|
||||
AssertFlag(() => new GuildPermissions(muteMembers: true), GuildPermission.MuteMembers);
|
||||
AssertFlag(() => new GuildPermissions(deafenMembers: true), GuildPermission.DeafenMembers);
|
||||
AssertFlag(() => new GuildPermissions(moveMembers: true), GuildPermission.MoveMembers);
|
||||
AssertFlag(() => new GuildPermissions(useVoiceActivation: true), GuildPermission.UseVAD);
|
||||
AssertFlag(() => new GuildPermissions(prioritySpeaker: true), GuildPermission.PrioritySpeaker);
|
||||
AssertFlag(() => new GuildPermissions(changeNickname: true), GuildPermission.ChangeNickname);
|
||||
AssertFlag(() => new GuildPermissions(manageNicknames: true), GuildPermission.ManageNicknames);
|
||||
AssertFlag(() => new GuildPermissions(manageRoles: true), GuildPermission.ManageRoles);
|
||||
AssertFlag(() => new GuildPermissions(manageWebhooks: true), GuildPermission.ManageWebhooks);
|
||||
AssertFlag(() => new GuildPermissions(manageEmojis: true), GuildPermission.ManageEmojis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="Discord.GuildPermissions.Modify(bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?)"/>
|
||||
/// with each of the parameters.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Modify()
|
||||
{
|
||||
// asserts that flag values can be checked
|
||||
// and that flag values can be toggled on and off
|
||||
// and that the behavior of ToList works as expected
|
||||
void AssertUtil(GuildPermission permission,
|
||||
Func<GuildPermissions, bool> has,
|
||||
Func<GuildPermissions, bool, GuildPermissions> modify)
|
||||
{
|
||||
var perm = new GuildPermissions();
|
||||
// ensure permission initially false
|
||||
// use both the function and Has to ensure that the GetPermission
|
||||
// function is working
|
||||
Assert.False(has(perm));
|
||||
Assert.False(perm.Has(permission));
|
||||
|
||||
// enable it, and ensure that it gets set
|
||||
perm = modify(perm, true);
|
||||
Assert.True(has(perm));
|
||||
Assert.True(perm.Has(permission));
|
||||
|
||||
// check ToList behavior
|
||||
var list = perm.ToList();
|
||||
Assert.Contains(permission, list);
|
||||
Assert.Single(list);
|
||||
|
||||
// set it false again
|
||||
perm = modify(perm, false);
|
||||
Assert.False(has(perm));
|
||||
Assert.False(perm.Has(permission));
|
||||
|
||||
// ensure that no perms are set now
|
||||
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);
|
||||
}
|
||||
|
||||
AssertUtil(GuildPermission.CreateInstantInvite, x => x.CreateInstantInvite, (p, enable) => p.Modify(createInstantInvite: enable));
|
||||
AssertUtil(GuildPermission.KickMembers, x => x.KickMembers, (p, enable) => p.Modify(kickMembers: enable));
|
||||
AssertUtil(GuildPermission.BanMembers, x => x.BanMembers, (p, enable) => p.Modify(banMembers: enable));
|
||||
AssertUtil(GuildPermission.Administrator, x => x.Administrator, (p, enable) => p.Modify(administrator: enable));
|
||||
AssertUtil(GuildPermission.ManageChannels, x => x.ManageChannels, (p, enable) => p.Modify(manageChannels: enable));
|
||||
AssertUtil(GuildPermission.ManageGuild, x => x.ManageGuild, (p, enable) => p.Modify(manageGuild: enable));
|
||||
AssertUtil(GuildPermission.AddReactions, x => x.AddReactions, (p, enable) => p.Modify(addReactions: enable));
|
||||
AssertUtil(GuildPermission.ViewAuditLog, x => x.ViewAuditLog, (p, enable) => p.Modify(viewAuditLog: enable));
|
||||
AssertUtil(GuildPermission.ViewChannel, x => x.ViewChannel, (p, enable) => p.Modify(viewChannel: enable));
|
||||
AssertUtil(GuildPermission.SendMessages, x => x.SendMessages, (p, enable) => p.Modify(sendMessages: enable));
|
||||
AssertUtil(GuildPermission.SendTTSMessages, x => x.SendTTSMessages, (p, enable) => p.Modify(sendTTSMessages: enable));
|
||||
AssertUtil(GuildPermission.ManageMessages, x => x.ManageMessages, (p, enable) => p.Modify(manageMessages: enable));
|
||||
AssertUtil(GuildPermission.EmbedLinks, x => x.EmbedLinks, (p, enable) => p.Modify(embedLinks: enable));
|
||||
AssertUtil(GuildPermission.AttachFiles, x => x.AttachFiles, (p, enable) => p.Modify(attachFiles: enable));
|
||||
AssertUtil(GuildPermission.ReadMessageHistory, x => x.ReadMessageHistory, (p, enable) => p.Modify(readMessageHistory: enable));
|
||||
AssertUtil(GuildPermission.MentionEveryone, x => x.MentionEveryone, (p, enable) => p.Modify(mentionEveryone: enable));
|
||||
AssertUtil(GuildPermission.UseExternalEmojis, x => x.UseExternalEmojis, (p, enable) => p.Modify(useExternalEmojis: enable));
|
||||
AssertUtil(GuildPermission.Connect, x => x.Connect, (p, enable) => p.Modify(connect: enable));
|
||||
AssertUtil(GuildPermission.Speak, x => x.Speak, (p, enable) => p.Modify(speak: enable));
|
||||
AssertUtil(GuildPermission.MuteMembers, x => x.MuteMembers, (p, enable) => p.Modify(muteMembers: enable));
|
||||
AssertUtil(GuildPermission.MoveMembers, x => x.MoveMembers, (p, enable) => p.Modify(moveMembers: enable));
|
||||
AssertUtil(GuildPermission.UseVAD, x => x.UseVAD, (p, enable) => p.Modify(useVoiceActivation: enable));
|
||||
AssertUtil(GuildPermission.ChangeNickname, x => x.ChangeNickname, (p, enable) => p.Modify(changeNickname: enable));
|
||||
AssertUtil(GuildPermission.ManageNicknames, x => x.ManageNicknames, (p, enable) => p.Modify(manageNicknames: enable));
|
||||
AssertUtil(GuildPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
|
||||
AssertUtil(GuildPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
|
||||
AssertUtil(GuildPermission.ManageEmojis, x => x.ManageEmojis, (p, enable) => p.Modify(manageEmojis: enable));
|
||||
}
|
||||
}
|
||||
}
|
||||
128
test/Discord.Net.Tests.Unit/MentionUtilsTests.cs
Normal file
128
test/Discord.Net.Tests.Unit/MentionUtilsTests.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the methods provided in <see cref="MentionUtils"/>.
|
||||
/// </summary>
|
||||
public class MentionUtilsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests <see cref="MentionUtils.MentionUser(string, bool)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MentionUser()
|
||||
{
|
||||
Assert.Equal("<@!123>", MentionUtils.MentionUser(123u));
|
||||
Assert.Equal("<@!123>", MentionUtils.MentionUser("123"));
|
||||
Assert.Equal("<@!123>", MentionUtils.MentionUser("123", true));
|
||||
Assert.Equal("<@123>", MentionUtils.MentionUser("123", false));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests <see cref="MentionUtils.MentionChannel(string)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MentionChannel()
|
||||
{
|
||||
Assert.Equal("<#123>", MentionUtils.MentionChannel(123u));
|
||||
Assert.Equal("<#123>", MentionUtils.MentionChannel("123"));
|
||||
}
|
||||
/// <summary>
|
||||
/// Tests <see cref="MentionUtils.MentionRole(string)"/>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MentionRole()
|
||||
{
|
||||
Assert.Equal("<@&123>", MentionUtils.MentionRole(123u));
|
||||
Assert.Equal("<@&123>", MentionUtils.MentionRole("123"));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("<@!123>", 123)]
|
||||
[InlineData("<@123>", 123)]
|
||||
public void ParseUser_Pass(string user, ulong id)
|
||||
{
|
||||
var parsed = MentionUtils.ParseUser(user);
|
||||
Assert.Equal(id, parsed);
|
||||
|
||||
// also check tryparse
|
||||
ulong result;
|
||||
Assert.True(MentionUtils.TryParseUser(user, out result));
|
||||
Assert.Equal(id, result);
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData("invalid")]
|
||||
[InlineData("<12!3@>")]
|
||||
[InlineData("<123>")]
|
||||
public void ParseUser_Fail(string user)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => MentionUtils.ParseUser(user));
|
||||
Assert.False(MentionUtils.TryParseUser(user, out _));
|
||||
}
|
||||
[Fact]
|
||||
public void ParseUser_Null()
|
||||
{
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseUser(null));
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseUser(null, out _));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("<#123>", 123)]
|
||||
public void ParseChannel_Pass(string channel, ulong id)
|
||||
{
|
||||
var parsed = MentionUtils.ParseChannel(channel);
|
||||
Assert.Equal(id, parsed);
|
||||
|
||||
// also check tryparse
|
||||
ulong result;
|
||||
Assert.True(MentionUtils.TryParseChannel(channel, out result));
|
||||
Assert.Equal(id, result);
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData("invalid")]
|
||||
[InlineData("<12#3>")]
|
||||
[InlineData("<123>")]
|
||||
public void ParseChannel_Fail(string channel)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => MentionUtils.ParseChannel(channel));
|
||||
Assert.False(MentionUtils.TryParseChannel(channel, out _));
|
||||
}
|
||||
[Fact]
|
||||
public void ParseChannel_Null()
|
||||
{
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseChannel(null));
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseChannel(null, out _));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("<@&123>", 123)]
|
||||
public void ParseRole_Pass(string role, ulong id)
|
||||
{
|
||||
var parsed = MentionUtils.ParseRole(role);
|
||||
Assert.Equal(id, parsed);
|
||||
|
||||
// also check tryparse
|
||||
ulong result;
|
||||
Assert.True(MentionUtils.TryParseRole(role, out result));
|
||||
Assert.Equal(id, result);
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(" ")]
|
||||
[InlineData("invalid")]
|
||||
[InlineData("<12@&3>")]
|
||||
[InlineData("<123>")]
|
||||
public void ParseRole_Fail(string role)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => MentionUtils.ParseRole(role));
|
||||
Assert.False(MentionUtils.TryParseRole(role, out _));
|
||||
}
|
||||
[Fact]
|
||||
public void ParseRole_Null()
|
||||
{
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseRole(null));
|
||||
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseRole(null, out _));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedCategoryChannel : ICategoryChannel
|
||||
{
|
||||
public int Position => throw new NotImplementedException();
|
||||
|
||||
public IGuild Guild => throw new NotImplementedException();
|
||||
|
||||
public ulong GuildId => throw new NotImplementedException();
|
||||
|
||||
public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IRole role)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IUser user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedDMChannel : IDMChannel
|
||||
{
|
||||
public IUser Recipient => throw new NotImplementedException();
|
||||
|
||||
public IReadOnlyCollection<IUser> Recipients => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task CloseAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDisposable EnterTypingState(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task TriggerTypingAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
105
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
Normal file
105
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Audio;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedGroupChannel : IGroupChannel
|
||||
{
|
||||
public IReadOnlyCollection<IUser> Recipients => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DisconnectAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDisposable EnterTypingState(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task LeaveAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task TriggerTypingAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a channel that is of an unrecognized type.
|
||||
/// </summary>
|
||||
internal sealed class MockedInvalidChannel : IChannel
|
||||
{
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
205
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs
Normal file
205
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedTextChannel : ITextChannel
|
||||
{
|
||||
public bool IsNsfw => throw new NotImplementedException();
|
||||
|
||||
public string Topic => throw new NotImplementedException();
|
||||
|
||||
public int SlowModeInterval => throw new NotImplementedException();
|
||||
|
||||
public string Mention => throw new NotImplementedException();
|
||||
|
||||
public ulong? CategoryId => throw new NotImplementedException();
|
||||
|
||||
public int Position => throw new NotImplementedException();
|
||||
|
||||
public IGuild Guild => throw new NotImplementedException();
|
||||
|
||||
public ulong GuildId => throw new NotImplementedException();
|
||||
|
||||
public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDisposable EnterTypingState(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IRole role)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IUser user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SyncPermissionsAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task TriggerTypingAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
Normal file
126
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Audio;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedVoiceChannel : IVoiceChannel
|
||||
{
|
||||
public int Bitrate => throw new NotImplementedException();
|
||||
|
||||
public int? UserLimit => throw new NotImplementedException();
|
||||
|
||||
public ulong? CategoryId => throw new NotImplementedException();
|
||||
|
||||
public int Position => throw new NotImplementedException();
|
||||
|
||||
public IGuild Guild => throw new NotImplementedException();
|
||||
|
||||
public ulong GuildId => throw new NotImplementedException();
|
||||
|
||||
public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DisconnectAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IRole role)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public OverwritePermissions? GetPermissionOverwrite(IUser user)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SyncPermissionsAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
test/Discord.Net.Tests.Unit/SnowflakeUtilsTests.cs
Normal file
24
test/Discord.Net.Tests.Unit/SnowflakeUtilsTests.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class SnowflakeUtilsTests
|
||||
{
|
||||
[Fact]
|
||||
public void FromSnowflake()
|
||||
{
|
||||
// snowflake from a userid
|
||||
var id = 163184946742034432u;
|
||||
Assert.Equal(new DateTime(2016, 3, 26, 7, 18, 43), SnowflakeUtils.FromSnowflake(id).UtcDateTime, TimeSpan.FromSeconds(1));
|
||||
}
|
||||
[Fact]
|
||||
public void ToSnowflake()
|
||||
{
|
||||
// most significant digits should match, but least significant digits cannot be determined from here
|
||||
Assert.Equal(163184946184192000u, SnowflakeUtils.ToSnowflake(new DateTimeOffset(2016, 3, 26, 7, 18, 43, TimeSpan.Zero)));
|
||||
}
|
||||
}
|
||||
}
|
||||
181
test/Discord.Net.Tests.Unit/TokenUtilsTests.cs
Normal file
181
test/Discord.Net.Tests.Unit/TokenUtilsTests.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="Discord.TokenUtils"/> methods.
|
||||
/// </summary>
|
||||
public class TokenUtilsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the usage of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
|
||||
/// to see that when a null, empty or whitespace-only string is passed as the token,
|
||||
/// it will throw an ArgumentNullException.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")] // string.Empty isn't a constant type
|
||||
[InlineData(" ")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("\t")]
|
||||
public void NullOrWhitespaceToken(string token)
|
||||
{
|
||||
// an ArgumentNullException should be thrown, regardless of the TokenType
|
||||
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bearer, token));
|
||||
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
|
||||
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Webhook, token));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
|
||||
/// to see that valid Webhook tokens do not throw Exceptions.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
[Theory]
|
||||
[InlineData("123123123")]
|
||||
// bot token
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
|
||||
// bearer token taken from discord docs
|
||||
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
|
||||
// client secret
|
||||
[InlineData("937it3ow87i4ery69876wqire")]
|
||||
public void WebhookTokenDoesNotThrowExceptions(string token)
|
||||
{
|
||||
TokenUtils.ValidateToken(TokenType.Webhook, token);
|
||||
}
|
||||
|
||||
// No tests for invalid webhook token behavior, because there is nothing there yet.
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
|
||||
/// to see that valid Webhook tokens do not throw Exceptions.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
[Theory]
|
||||
[InlineData("123123123")]
|
||||
// bot token
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
|
||||
// bearer token taken from discord docs
|
||||
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
|
||||
// client secret
|
||||
[InlineData("937it3ow87i4ery69876wqire")]
|
||||
public void BearerTokenDoesNotThrowExceptions(string token)
|
||||
{
|
||||
TokenUtils.ValidateToken(TokenType.Bearer, token);
|
||||
}
|
||||
|
||||
// No tests for invalid bearer token behavior, because there is nothing there yet.
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
|
||||
/// to see that valid Bot tokens do not throw Exceptions.
|
||||
/// Valid Bot tokens can be strings of length 58 or above.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
// missing a single character from the end, 58 char. still should be valid
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKW")]
|
||||
// 59 char token
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWss")]
|
||||
public void BotTokenDoesNotThrowExceptions(string token)
|
||||
{
|
||||
// This example token is pulled from the Discord Docs
|
||||
// https://discordapp.com/developers/docs/reference#authentication-example-bot-token-authorization-header
|
||||
// should not throw any exception
|
||||
TokenUtils.ValidateToken(TokenType.Bot, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the usage of <see cref="TokenUtils.ValidateToken(TokenType, string)"/> with
|
||||
/// a Bot token that is invalid.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("This is invalid")]
|
||||
// bearer token
|
||||
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
|
||||
// client secret
|
||||
[InlineData("937it3ow87i4ery69876wqire")]
|
||||
// 57 char bot token
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kK")]
|
||||
// ends with invalid characters
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k ")]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k\n")]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k\t")]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k\r\n")]
|
||||
// starts with invalid characters
|
||||
[InlineData(" MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k")]
|
||||
[InlineData("\nMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k")]
|
||||
[InlineData("\tMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k")]
|
||||
[InlineData("\r\nMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7k")]
|
||||
[InlineData("This is an invalid token, but it passes the check for string length.")]
|
||||
// valid token, but passed in twice
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWsMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
|
||||
public void BotTokenInvalidThrowsArgumentException(string token)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
|
||||
/// to see that an <see cref="ArgumentException"/> is thrown when an invalid
|
||||
/// <see cref="TokenType"/> is supplied as a parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="TokenType.User"/> type is treated as an invalid <see cref="TokenType"/>.
|
||||
/// </remarks>
|
||||
[Theory]
|
||||
// TokenType.User
|
||||
[InlineData(0)]
|
||||
// out of range TokenType
|
||||
[InlineData(-1)]
|
||||
[InlineData(4)]
|
||||
[InlineData(7)]
|
||||
public void UnrecognizedTokenType(int type)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
TokenUtils.ValidateToken((TokenType)type, "MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the <see cref="TokenUtils.CheckBotTokenValidity(string)"/> method for expected output.
|
||||
/// </summary>
|
||||
/// <param name="token"> The Bot Token to test.</param>
|
||||
/// <param name="expected"> The expected result. </param>
|
||||
[Theory]
|
||||
// this method only checks the first part of the JWT
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4..", true)]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kK", true)]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4. this part is invalid. this part is also invalid", true)]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.", false)]
|
||||
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4", false)]
|
||||
[InlineData("NDI4NDc3OTQ0MDA5MTk1NTIw.xxxx.xxxxx", true)]
|
||||
// should not throw an unexpected exception
|
||||
[InlineData("", false)]
|
||||
[InlineData(null, false)]
|
||||
public void CheckBotTokenValidity(string token, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, TokenUtils.CheckBotTokenValidity(token));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
// cannot pass a ulong? as a param in InlineData, so have to have a separate param
|
||||
// indicating if a value is null
|
||||
[InlineData("NDI4NDc3OTQ0MDA5MTk1NTIw", false, 428477944009195520)]
|
||||
// should return null w/o throwing other exceptions
|
||||
[InlineData("", true, 0)]
|
||||
[InlineData(" ", true, 0)]
|
||||
[InlineData(null, true, 0)]
|
||||
[InlineData("these chars aren't allowed @U#)*@#!)*", true, 0)]
|
||||
public void DecodeBase64UserId(string encodedUserId, bool isNull, ulong expectedUserId)
|
||||
{
|
||||
var result = TokenUtils.DecodeBase64UserId(encodedUserId);
|
||||
if (isNull)
|
||||
Assert.Null(result);
|
||||
else
|
||||
Assert.Equal(expectedUserId, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
test/Discord.Net.Tests.Unit/TypeReaderTests.cs
Normal file
142
test/Discord.Net.Tests.Unit/TypeReaderTests.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using Discord.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public sealed class TypeReaderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task TestNamedArgumentReader()
|
||||
{
|
||||
using (var commands = new CommandService())
|
||||
{
|
||||
var module = await commands.AddModuleAsync<TestModule>(null);
|
||||
|
||||
Assert.NotNull(module);
|
||||
Assert.NotEmpty(module.Commands);
|
||||
|
||||
var cmd = module.Commands[0];
|
||||
Assert.NotNull(cmd);
|
||||
Assert.NotEmpty(cmd.Parameters);
|
||||
|
||||
var param = cmd.Parameters[0];
|
||||
Assert.NotNull(param);
|
||||
Assert.True(param.IsRemainder);
|
||||
|
||||
var result = await param.ParseAsync(null, "bar: hello foo: 42");
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var m = result.BestMatch as ArgumentType;
|
||||
Assert.NotNull(m);
|
||||
Assert.Equal(expected: 42, actual: m.Foo);
|
||||
Assert.Equal(expected: "hello", actual: m.Bar);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQuotedArgumentValue()
|
||||
{
|
||||
using (var commands = new CommandService())
|
||||
{
|
||||
var module = await commands.AddModuleAsync<TestModule>(null);
|
||||
|
||||
Assert.NotNull(module);
|
||||
Assert.NotEmpty(module.Commands);
|
||||
|
||||
var cmd = module.Commands[0];
|
||||
Assert.NotNull(cmd);
|
||||
Assert.NotEmpty(cmd.Parameters);
|
||||
|
||||
var param = cmd.Parameters[0];
|
||||
Assert.NotNull(param);
|
||||
Assert.True(param.IsRemainder);
|
||||
|
||||
var result = await param.ParseAsync(null, "foo: 42 bar: 《hello》");
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var m = result.BestMatch as ArgumentType;
|
||||
Assert.NotNull(m);
|
||||
Assert.Equal(expected: 42, actual: m.Foo);
|
||||
Assert.Equal(expected: "hello", actual: m.Bar);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestNonPatternInput()
|
||||
{
|
||||
using (var commands = new CommandService())
|
||||
{
|
||||
var module = await commands.AddModuleAsync<TestModule>(null);
|
||||
|
||||
Assert.NotNull(module);
|
||||
Assert.NotEmpty(module.Commands);
|
||||
|
||||
var cmd = module.Commands[0];
|
||||
Assert.NotNull(cmd);
|
||||
Assert.NotEmpty(cmd.Parameters);
|
||||
|
||||
var param = cmd.Parameters[0];
|
||||
Assert.NotNull(param);
|
||||
Assert.True(param.IsRemainder);
|
||||
|
||||
var result = await param.ParseAsync(null, "foobar");
|
||||
Assert.False(result.IsSuccess);
|
||||
Assert.Equal(expected: CommandError.Exception, actual: result.Error);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestMultiple()
|
||||
{
|
||||
using (var commands = new CommandService())
|
||||
{
|
||||
var module = await commands.AddModuleAsync<TestModule>(null);
|
||||
|
||||
Assert.NotNull(module);
|
||||
Assert.NotEmpty(module.Commands);
|
||||
|
||||
var cmd = module.Commands[0];
|
||||
Assert.NotNull(cmd);
|
||||
Assert.NotEmpty(cmd.Parameters);
|
||||
|
||||
var param = cmd.Parameters[0];
|
||||
Assert.NotNull(param);
|
||||
Assert.True(param.IsRemainder);
|
||||
|
||||
var result = await param.ParseAsync(null, "manyints: \"1, 2, 3, 4, 5, 6, 7\"");
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var m = result.BestMatch as ArgumentType;
|
||||
Assert.NotNull(m);
|
||||
Assert.Equal(expected: new int[] { 1, 2, 3, 4, 5, 6, 7 }, actual: m.ManyInts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[NamedArgumentType]
|
||||
public sealed class ArgumentType
|
||||
{
|
||||
public int Foo { get; set; }
|
||||
|
||||
[OverrideTypeReader(typeof(CustomTypeReader))]
|
||||
public string Bar { get; set; }
|
||||
|
||||
public IEnumerable<int> ManyInts { get; set; }
|
||||
}
|
||||
|
||||
public sealed class CustomTypeReader : TypeReader
|
||||
{
|
||||
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
|
||||
=> Task.FromResult(TypeReaderResult.FromSuccess(input));
|
||||
}
|
||||
|
||||
public sealed class TestModule : ModuleBase
|
||||
{
|
||||
[Command("test")]
|
||||
public Task TestCommand(ArgumentType arg) => Task.Delay(0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user