Added test files
This commit is contained in:
parent
a238d06ce3
commit
21844d5a58
25 changed files with 2622 additions and 5 deletions
|
@ -0,0 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</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.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.7.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,53 @@
|
|||
using Discord.API;
|
||||
using Discord.API.Rest;
|
||||
using Discord.Net;
|
||||
using Discord.Rest;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
[CollectionDefinition(nameof(DiscordRestApiClientTests), DisableParallelization = true)]
|
||||
public class DiscordRestApiClientTests : IClassFixture<RestGuildFixture>, IAsyncDisposable
|
||||
{
|
||||
private readonly DiscordRestApiClient _apiClient;
|
||||
private readonly IGuild _guild;
|
||||
private readonly ITextChannel _channel;
|
||||
|
||||
public DiscordRestApiClientTests(RestGuildFixture guildFixture)
|
||||
{
|
||||
_guild = guildFixture.Guild;
|
||||
_apiClient = guildFixture.Client.ApiClient;
|
||||
_channel = _guild.CreateTextChannelAsync("testChannel").Result;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _channel.DeleteAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UploadFile_WithMaximumSize_DontThrowsException()
|
||||
{
|
||||
var fileSize = GuildHelper.GetUploadLimit(_guild.PremiumTier);
|
||||
using var stream = new MemoryStream(new byte[fileSize]);
|
||||
|
||||
await _apiClient.UploadFileAsync(_channel.Id, new UploadFileParams(new FileAttachment(stream, "filename")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UploadFile_WithOverSize_ThrowsException()
|
||||
{
|
||||
var fileSize = GuildHelper.GetUploadLimit(_guild.PremiumTier) + 1;
|
||||
using var stream = new MemoryStream(new byte[fileSize]);
|
||||
|
||||
Func<Task> upload = async () =>
|
||||
await _apiClient.UploadFileAsync(_channel.Id, new UploadFileParams(new FileAttachment(stream, "filename")));
|
||||
|
||||
await upload.Should().ThrowExactlyAsync<HttpException>()
|
||||
.Where(e => e.DiscordCode == DiscordErrorCode.RequestEntityTooLarge);
|
||||
}
|
||||
}
|
238
test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs
Normal file
238
test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs
Normal file
|
@ -0,0 +1,238 @@
|
|||
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(stream: true), ChannelPermission.Stream);
|
||||
AssertFlag(() => new ChannelPermissions(manageRoles: true), ChannelPermission.ManageRoles);
|
||||
AssertFlag(() => new ChannelPermissions(manageWebhooks: true), ChannelPermission.ManageWebhooks);
|
||||
AssertFlag(() => new ChannelPermissions(useApplicationCommands: true), ChannelPermission.UseApplicationCommands);
|
||||
AssertFlag(() => new ChannelPermissions(createPrivateThreads: true), ChannelPermission.CreatePrivateThreads);
|
||||
AssertFlag(() => new ChannelPermissions(createPublicThreads: true), ChannelPermission.CreatePublicThreads);
|
||||
AssertFlag(() => new ChannelPermissions(sendMessagesInThreads: true), ChannelPermission.SendMessagesInThreads);
|
||||
AssertFlag(() => new ChannelPermissions(startEmbeddedActivities: true), ChannelPermission.StartEmbeddedActivities);
|
||||
AssertFlag(() => new ChannelPermissions(useSoundboard: true), ChannelPermission.UseSoundboard);
|
||||
AssertFlag(() => new ChannelPermissions(createEvents: true), ChannelPermission.CreateEvents);
|
||||
AssertFlag(() => new ChannelPermissions(sendVoiceMessages: true), ChannelPermission.SendVoiceMessages);
|
||||
AssertFlag(() => new ChannelPermissions(useClydeAI: true), ChannelPermission.UseClydeAI);
|
||||
AssertFlag(() => new ChannelPermissions(setVoiceChannelStatus: true), ChannelPermission.SetVoiceChannelStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the behavior of <see cref="Discord.ChannelPermissions.Modify"/>
|
||||
/// 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));
|
||||
AssertUtil(ChannelPermission.Stream, x => x.Stream, (p, enable) => p.Modify(stream: enable));
|
||||
AssertUtil(ChannelPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable));
|
||||
AssertUtil(ChannelPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable));
|
||||
AssertUtil(ChannelPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: 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.Throws<ArgumentException>(() => new Color(uint.MaxValue));
|
||||
}
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
55
test/Discord.Net.Tests.Unit/CommandBuilderTests.cs
Normal file
55
test/Discord.Net.Tests.Unit/CommandBuilderTests.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
using Discord;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class CommandBuilderTests
|
||||
{
|
||||
[Fact]
|
||||
public void BuildSimpleSlashCommand()
|
||||
{
|
||||
var command = new SlashCommandBuilder()
|
||||
.WithName("command")
|
||||
.WithDescription("description")
|
||||
.AddOption(
|
||||
"option1",
|
||||
ApplicationCommandOptionType.String,
|
||||
"option1 description",
|
||||
isRequired: true,
|
||||
choices: new[]
|
||||
{
|
||||
new ApplicationCommandOptionChoiceProperties()
|
||||
{
|
||||
Name = "choice1", Value = "1"
|
||||
}
|
||||
})
|
||||
.AddOptions(new SlashCommandOptionBuilder()
|
||||
.WithName("option2")
|
||||
.WithDescription("option2 description")
|
||||
.WithType(ApplicationCommandOptionType.String)
|
||||
.WithRequired(true)
|
||||
.AddChannelType(ChannelType.Text)
|
||||
.AddChoice("choice1", "1")
|
||||
.AddChoice("choice2", "2"));
|
||||
command.Build();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildSubSlashCommand()
|
||||
{
|
||||
var command = new SlashCommandBuilder()
|
||||
.WithName("command").WithDescription("Command desc.")
|
||||
.AddOptions(new SlashCommandOptionBuilder()
|
||||
.WithType(ApplicationCommandOptionType.SubCommand)
|
||||
.WithName("subcommand").WithDescription("Subcommand desc.")
|
||||
.AddOptions(
|
||||
new SlashCommandOptionBuilder()
|
||||
.WithType(ApplicationCommandOptionType.String)
|
||||
.WithName("name1").WithDescription("desc1"),
|
||||
new SlashCommandOptionBuilder()
|
||||
.WithType(ApplicationCommandOptionType.String)
|
||||
.WithName("name2").WithDescription("desc2")));
|
||||
command.Build();
|
||||
}
|
||||
}
|
|
@ -1,10 +1,25 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<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.WebSocket/Discord.Net.WebSocket.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.7.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
426
test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs
Normal file
426
test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs
Normal file
|
@ -0,0 +1,426 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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', 4097);
|
||||
}
|
||||
foreach (var description in GetInvalid())
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new EmbedBuilder().WithDescription(description));
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
var b = new EmbedBuilder
|
||||
{
|
||||
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', 4096);
|
||||
}
|
||||
foreach (var description in GetValid())
|
||||
{
|
||||
var b = new EmbedBuilder().WithDescription(description);
|
||||
Assert.Equal(description, b.Description);
|
||||
|
||||
b = new EmbedBuilder
|
||||
{
|
||||
Description = description
|
||||
};
|
||||
Assert.Equal(description, b.Description);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that valid url does 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
|
||||
{
|
||||
Url = url,
|
||||
ImageUrl = url,
|
||||
ThumbnailUrl = url
|
||||
};
|
||||
Assert.Equal(result.Url, url);
|
||||
Assert.Equal(result.ImageUrl, url);
|
||||
Assert.Equal(result.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(DateTimeOffset.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
|
||||
{
|
||||
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 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
|
||||
{
|
||||
IsInline = true,
|
||||
Name = "name",
|
||||
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 _));
|
||||
}
|
||||
}
|
||||
}
|
78
test/Discord.Net.Tests.Unit/FormatTests.cs
Normal file
78
test/Discord.Net.Tests.Unit/FormatTests.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
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\_")]
|
||||
[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"));
|
||||
}
|
||||
[Fact]
|
||||
public void QuoteNullString()
|
||||
{
|
||||
Assert.Null(Format.Quote(null));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("", "")]
|
||||
[InlineData("\n", "\n")]
|
||||
[InlineData("foo\n\nbar", "> foo\n> \n> bar")]
|
||||
[InlineData("input", "> input")] // single line
|
||||
// should work with CR or CRLF
|
||||
[InlineData("inb4\ngreentext", "> inb4\n> greentext")]
|
||||
[InlineData("inb4\r\ngreentext", "> inb4\r\n> greentext")]
|
||||
public void Quote(string input, string expected)
|
||||
{
|
||||
Assert.Equal(expected, Format.Quote(input));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(null, null)]
|
||||
[InlineData("", "")]
|
||||
[InlineData("\n", "\n")]
|
||||
[InlineData("foo\n\nbar", ">>> foo\n\nbar")]
|
||||
[InlineData("input", ">>> input")] // single line
|
||||
// should work with CR or CRLF
|
||||
[InlineData("inb4\ngreentext", ">>> inb4\ngreentext")]
|
||||
[InlineData("inb4\r\ngreentext", ">>> inb4\r\ngreentext")]
|
||||
public void BlockQuote(string input, string expected)
|
||||
{
|
||||
Assert.Equal(expected, Format.BlockQuote(input));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("", "")]
|
||||
[InlineData("\n", "\n")]
|
||||
[InlineData("**hi**", "hi")]
|
||||
[InlineData("__uwu__", "uwu")]
|
||||
[InlineData(">>__uwu__", "uwu")]
|
||||
[InlineData("```uwu```", "uwu")]
|
||||
[InlineData("~uwu~", "uwu")]
|
||||
[InlineData("berries __and__ *Cream**, I'm a little lad who loves berries and cream", "berries and Cream, I'm a little lad who loves berries and cream")]
|
||||
public void StripMarkdown(string input, string expected)
|
||||
{
|
||||
var test = Format.StripMarkDown(input);
|
||||
Assert.Equal(expected, test);
|
||||
}
|
||||
}
|
||||
}
|
23
test/Discord.Net.Tests.Unit/GuildHelperTests.cs
Normal file
23
test/Discord.Net.Tests.Unit/GuildHelperTests.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using Discord.Rest;
|
||||
using NSubstitute;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class GuildHelperTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(PremiumTier.None, 25)]
|
||||
[InlineData(PremiumTier.Tier1, 25)]
|
||||
[InlineData(PremiumTier.Tier2, 50)]
|
||||
[InlineData(PremiumTier.Tier3, 100)]
|
||||
public void GetUploadLimit(PremiumTier tier, ulong factor)
|
||||
{
|
||||
var expected = factor * (ulong)Math.Pow(2, 20);
|
||||
|
||||
var actual = GuildHelper.GetUploadLimit(tier);
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
195
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
Normal file
195
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
Normal file
|
@ -0,0 +1,195 @@
|
|||
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(viewGuildInsights: true), GuildPermission.ViewGuildInsights);
|
||||
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(stream: true), GuildPermission.Stream);
|
||||
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(manageEmojisAndStickers: true), GuildPermission.ManageEmojisAndStickers);
|
||||
AssertFlag(() => new GuildPermissions(useApplicationCommands: true), GuildPermission.UseApplicationCommands);
|
||||
AssertFlag(() => new GuildPermissions(requestToSpeak: true), GuildPermission.RequestToSpeak);
|
||||
AssertFlag(() => new GuildPermissions(manageEvents: true), GuildPermission.ManageEvents);
|
||||
AssertFlag(() => new GuildPermissions(manageThreads: true), GuildPermission.ManageThreads);
|
||||
AssertFlag(() => new GuildPermissions(createPublicThreads: true), GuildPermission.CreatePublicThreads);
|
||||
AssertFlag(() => new GuildPermissions(createPrivateThreads: true), GuildPermission.CreatePrivateThreads);
|
||||
AssertFlag(() => new GuildPermissions(useExternalStickers: true), GuildPermission.UseExternalStickers);
|
||||
AssertFlag(() => new GuildPermissions(moderateMembers: true), GuildPermission.ModerateMembers);
|
||||
AssertFlag(() => new GuildPermissions(viewMonetizationAnalytics: true), GuildPermission.ViewMonetizationAnalytics);
|
||||
AssertFlag(() => new GuildPermissions(useSoundboard: true), GuildPermission.UseSoundboard);
|
||||
AssertFlag(() => new GuildPermissions(sendVoiceMessages: true), GuildPermission.SendVoiceMessages);
|
||||
AssertFlag(() => new GuildPermissions(useClydeAI: true), GuildPermission.UseClydeAI);
|
||||
AssertFlag(() => new GuildPermissions(createGuildExpressions: true), GuildPermission.CreateGuildExpressions);
|
||||
AssertFlag(() => new GuildPermissions(setVoiceChannelStatus: true), GuildPermission.SetVoiceChannelStatus);
|
||||
}
|
||||
|
||||
/// <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.ViewGuildInsights, x => x.ViewGuildInsights, (p, enable) => p.Modify(viewGuildInsights: 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.ManageEmojisAndStickers, x => x.ManageEmojisAndStickers, (p, enable) => p.Modify(manageEmojisAndStickers: enable));
|
||||
AssertUtil(GuildPermission.UseApplicationCommands, x => x.UseApplicationCommands, (p, enable) => p.Modify(useApplicationCommands: enable));
|
||||
AssertUtil(GuildPermission.RequestToSpeak, x => x.RequestToSpeak, (p, enable) => p.Modify(requestToSpeak: enable));
|
||||
AssertUtil(GuildPermission.ManageEvents, x => x.ManageEvents, (p, enable) => p.Modify(manageEvents: enable));
|
||||
AssertUtil(GuildPermission.ManageThreads, x => x.ManageThreads, (p, enable) => p.Modify(manageThreads: enable));
|
||||
AssertUtil(GuildPermission.CreatePublicThreads, x => x.CreatePublicThreads, (p, enable) => p.Modify(createPublicThreads: enable));
|
||||
AssertUtil(GuildPermission.CreatePrivateThreads, x => x.CreatePrivateThreads, (p, enable) => p.Modify(createPrivateThreads: enable));
|
||||
AssertUtil(GuildPermission.UseExternalStickers, x => x.UseExternalStickers, (p, enable) => p.Modify(useExternalStickers: enable));
|
||||
AssertUtil(GuildPermission.ModerateMembers, x => x.ModerateMembers, (p, enable) => p.Modify(moderateMembers: enable));
|
||||
AssertUtil(GuildPermission.ViewMonetizationAnalytics, x => x.ViewMonetizationAnalytics, (p, enable) => p.Modify(viewMonetizationAnalytics: enable));
|
||||
AssertUtil(GuildPermission.UseSoundboard, x => x.UseSoundboard, (p, enable) => p.Modify(useSoundboard: enable));
|
||||
AssertUtil(GuildPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable));
|
||||
AssertUtil(GuildPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable));
|
||||
AssertUtil(GuildPermission.CreateGuildExpressions, x => x.CreateGuildExpressions, (p, enable) => p.Modify(createGuildExpressions: enable));
|
||||
AssertUtil(GuildPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable));
|
||||
}
|
||||
}
|
||||
}
|
120
test/Discord.Net.Tests.Unit/MentionUtilsTests.cs
Normal file
120
test/Discord.Net.Tests.Unit/MentionUtilsTests.cs
Normal file
|
@ -0,0 +1,120 @@
|
|||
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"));
|
||||
}
|
||||
/// <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);
|
||||
|
||||
Assert.True(MentionUtils.TryParseUser(user, out ulong 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);
|
||||
|
||||
Assert.True(MentionUtils.TryParseChannel(channel, out ulong 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);
|
||||
|
||||
Assert.True(MentionUtils.TryParseRole(role, out ulong 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 _));
|
||||
}
|
||||
}
|
||||
}
|
118
test/Discord.Net.Tests.Unit/MessageHelperTests.cs
Normal file
118
test/Discord.Net.Tests.Unit/MessageHelperTests.cs
Normal file
|
@ -0,0 +1,118 @@
|
|||
using Discord.Rest;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="MessageHelper"/> parsing.
|
||||
/// </summary>
|
||||
public class MessageHelperTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests that no tags are parsed while in code blocks
|
||||
/// or inline code.
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("`@everyone`")]
|
||||
[InlineData("`<@163184946742034432>`")]
|
||||
[InlineData("```@everyone```")]
|
||||
[InlineData("```cs \n @everyone```")]
|
||||
[InlineData("```cs <@163184946742034432> ```")]
|
||||
[InlineData("``` test ``` ```cs <@163184946742034432> ```")]
|
||||
[InlineData("`<:test:537920404019216384>`")]
|
||||
[InlineData("``` @everyone `")] // discord client handles these weirdly
|
||||
[InlineData("``` @everyone ``")]
|
||||
[InlineData("` @here `")]
|
||||
[InlineData("` @everyone @here <@163184946742034432> <@&163184946742034432> <#163184946742034432> <:test:537920404019216384> `")]
|
||||
public void ParseTagsInCode(string testData)
|
||||
{
|
||||
// don't care that I'm passing in null channels/guilds/users
|
||||
// as they shouldn't be required
|
||||
var result = MessageHelper.ParseTags(testData, null, null, null);
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
/// <summary> Tests parsing tags that surround inline code or a code block. </summary>
|
||||
[Theory]
|
||||
[InlineData("`` <@&163184946742034432>")]
|
||||
[InlineData("``` code block 1 ``` ``` code block 2 ``` <@&163184946742034432>")]
|
||||
[InlineData("` code block 1 ``` ` code block 2 ``` <@&163184946742034432>")]
|
||||
[InlineData("<@&163184946742034432> ``` code block 1 ```")]
|
||||
[InlineData("``` code ``` ``` code ``` @here ``` code ``` ``` more ```")]
|
||||
[InlineData("``` code ``` @here ``` more ```")]
|
||||
public void ParseTagsAroundCode(string testData)
|
||||
{
|
||||
// don't care that I'm passing in null channels/guilds/users
|
||||
// as they shouldn't be required
|
||||
var result = MessageHelper.ParseTags(testData, null, null, null);
|
||||
Assert.NotEmpty(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"\` @everyone \`")]
|
||||
[InlineData(@"\`\`\` @everyone \`\`\`")]
|
||||
[InlineData(@"hey\`\`\`@everyone\`\`\`!!")]
|
||||
public void IgnoreEscapedCodeBlocks(string testData)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(testData, null, null, null);
|
||||
Assert.NotEmpty(result);
|
||||
}
|
||||
|
||||
// cannot test parsing a user, as it uses the ReadOnlyCollection<IUser> arg.
|
||||
// this could be done if mocked entities are merged in PR #1290
|
||||
|
||||
/// <summary> Tests parsing a mention of a role. </summary>
|
||||
[Theory]
|
||||
[InlineData("<@&163184946742034432>")]
|
||||
[InlineData("**<@&163184946742034432>**")]
|
||||
[InlineData("__<@&163184946742034432>__")]
|
||||
[InlineData("<><@&163184946742034432>")]
|
||||
public void ParseRole(string roleTag)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(roleTag, null, null, null);
|
||||
Assert.Contains(result, x => x.Type == TagType.RoleMention);
|
||||
}
|
||||
|
||||
/// <summary> Tests parsing a channel. </summary>
|
||||
[Theory]
|
||||
[InlineData("<#429115823748284417>")]
|
||||
[InlineData("**<#429115823748284417>**")]
|
||||
[InlineData("<><#429115823748284417>")]
|
||||
public void ParseChannel(string channelTag)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(channelTag, null, null, null);
|
||||
Assert.Contains(result, x => x.Type == TagType.ChannelMention);
|
||||
}
|
||||
|
||||
/// <summary> Tests parsing an emoji. </summary>
|
||||
[Theory]
|
||||
[InlineData("<:test:537920404019216384>")]
|
||||
[InlineData("**<:test:537920404019216384>**")]
|
||||
[InlineData("<><:test:537920404019216384>")]
|
||||
public void ParseEmoji(string emoji)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(emoji, null, null, null);
|
||||
Assert.Contains(result, x => x.Type == TagType.Emoji);
|
||||
}
|
||||
|
||||
/// <summary> Tests parsing a mention of @everyone. </summary>
|
||||
[Theory]
|
||||
[InlineData("@everyone")]
|
||||
[InlineData("**@everyone**")]
|
||||
public void ParseEveryone(string everyone)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(everyone, null, null, null);
|
||||
Assert.Contains(result, x => x.Type == TagType.EveryoneMention);
|
||||
}
|
||||
|
||||
/// <summary> Tests parsing a mention of @here. </summary>
|
||||
[Theory]
|
||||
[InlineData("@here")]
|
||||
[InlineData("**@here**")]
|
||||
public void ParseHere(string here)
|
||||
{
|
||||
var result = MessageHelper.ParseTags(here, null, null, null);
|
||||
Assert.Contains(result, x => x.Type == TagType.HereMention);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
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 ChannelFlags Flags => 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,92 @@
|
|||
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 Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, 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 TriggerTypingAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => 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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
119
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
Normal file
119
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
using Discord.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
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 string RTCRegion => throw new NotImplementedException();
|
||||
|
||||
public Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false, bool disconnect = true)
|
||||
{
|
||||
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<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DisconnectAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options)
|
||||
{
|
||||
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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task TriggerTypingAsync(RequestOptions options = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => 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();
|
||||
}
|
||||
}
|
||||
}
|
227
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs
Normal file
227
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs
Normal file
|
@ -0,0 +1,227 @@
|
|||
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 int DefaultSlowModeInterval => throw new NotImplementedException();
|
||||
|
||||
public ThreadArchiveDuration DefaultArchiveDuration => 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 ChannelFlags Flags => 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<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
=> throw new NotImplementedException();
|
||||
public Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), 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 Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, 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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IReadOnlyCollection<IThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
100
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
Normal file
100
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
using Discord.Audio;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal sealed class MockedVoiceChannel : IVoiceChannel
|
||||
{
|
||||
public int DefaultSlowModeInterval => throw new NotImplementedException();
|
||||
|
||||
public int Bitrate => throw new NotImplementedException();
|
||||
|
||||
public int? UserLimit => throw new NotImplementedException();
|
||||
public string Topic { get; }
|
||||
public int SlowModeInterval { get; }
|
||||
public ThreadArchiveDuration DefaultArchiveDuration { get; }
|
||||
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 Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
|
||||
public Task<IThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null) => throw new NotImplementedException();
|
||||
|
||||
public Task<IReadOnlyCollection<IThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null) => 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 RTCRegion => throw new NotImplementedException();
|
||||
|
||||
public string Name => throw new NotImplementedException();
|
||||
|
||||
public DateTimeOffset CreatedAt => throw new NotImplementedException();
|
||||
|
||||
public ulong Id => throw new NotImplementedException();
|
||||
|
||||
public string Mention => throw new NotImplementedException();
|
||||
|
||||
public ChannelFlags Flags => throw new NotImplementedException();
|
||||
|
||||
public VideoQualityMode VideoQualityMode => throw new NotImplementedException();
|
||||
public bool IsNsfw { get; }
|
||||
|
||||
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, bool disconnect = true) => 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<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, 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 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<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 ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task SetStatusAsync(string status, RequestOptions options = null) => throw new NotImplementedException();
|
||||
|
||||
public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> 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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => 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, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => 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();
|
||||
public Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, 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();
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// See https://aka.ms/new-console-template for more information
|
||||
Console.WriteLine("Hello, World!");
|
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)));
|
||||
}
|
||||
}
|
||||
}
|
71
test/Discord.Net.Tests.Unit/TimeSpanTypeReaderTests.cs
Normal file
71
test/Discord.Net.Tests.Unit/TimeSpanTypeReaderTests.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using Discord.Commands;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public class TimeSpanTypeReaderTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("4d3h2m1s", false)] // tests format "%d'd'%h'h'%m'm'%s's'"
|
||||
[InlineData("4d3h2m", false)] // tests format "%d'd'%h'h'%m'm'"
|
||||
[InlineData("4d3h1s", false)] // tests format "%d'd'%h'h'%s's'"
|
||||
[InlineData("4d3h", false)] // tests format "%d'd'%h'h'"
|
||||
[InlineData("4d2m1s", false)] // tests format "%d'd'%m'm'%s's'"
|
||||
[InlineData("4d2m", false)] // tests format "%d'd'%m'm'"
|
||||
[InlineData("4d1s", false)] // tests format "%d'd'%s's'"
|
||||
[InlineData("4d", false)] // tests format "%d'd'"
|
||||
[InlineData("3h2m1s", false)] // tests format "%h'h'%m'm'%s's'"
|
||||
[InlineData("3h2m", false)] // tests format "%h'h'%m'm'"
|
||||
[InlineData("3h1s", false)] // tests format "%h'h'%s's'"
|
||||
[InlineData("3h", false)] // tests format "%h'h'"
|
||||
[InlineData("2m1s", false)] // tests format "%m'm'%s's'"
|
||||
[InlineData("2m", false)] // tests format "%m'm'"
|
||||
[InlineData("1s", false)] // tests format "%s's'"
|
||||
// Negatives
|
||||
[InlineData("-4d3h2m1s", true)] // tests format "-%d'd'%h'h'%m'm'%s's'"
|
||||
[InlineData("-4d3h2m", true)] // tests format "-%d'd'%h'h'%m'm'"
|
||||
[InlineData("-4d3h1s", true)] // tests format "-%d'd'%h'h'%s's'"
|
||||
[InlineData("-4d3h", true)] // tests format "-%d'd'%h'h'"
|
||||
[InlineData("-4d2m1s", true)] // tests format "-%d'd'%m'm'%s's'"
|
||||
[InlineData("-4d2m", true)] // tests format "-%d'd'%m'm'"
|
||||
[InlineData("-4d1s", true)] // tests format "-%d'd'%s's'"
|
||||
[InlineData("-4d", true)] // tests format "-%d'd'"
|
||||
[InlineData("-3h2m1s", true)] // tests format "-%h'h'%m'm'%s's'"
|
||||
[InlineData("-3h2m", true)] // tests format "-%h'h'%m'm'"
|
||||
[InlineData("-3h1s", true)] // tests format "-%h'h'%s's'"
|
||||
[InlineData("-3h", true)] // tests format "-%h'h'"
|
||||
[InlineData("-2m1s", true)] // tests format "-%m'm'%s's'"
|
||||
[InlineData("-2m", true)] // tests format "-%m'm'"
|
||||
[InlineData("-1s", true)] // tests format "-%s's'"
|
||||
public async Task TestTimeSpanParse(string input, bool isNegative)
|
||||
{
|
||||
var reader = new TimeSpanTypeReader();
|
||||
var result = await reader.ReadAsync(null, input, null);
|
||||
Assert.True(result.IsSuccess);
|
||||
|
||||
var actual = (TimeSpan)result.BestMatch;
|
||||
Assert.True(actual != TimeSpan.Zero);
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
Assert.True(actual < TimeSpan.Zero);
|
||||
|
||||
Assert.True(actual.Seconds == 0 || actual.Seconds == -1);
|
||||
Assert.True(actual.Minutes == 0 || actual.Minutes == -2);
|
||||
Assert.True(actual.Hours == 0 || actual.Hours == -3);
|
||||
Assert.True(actual.Days == 0 || actual.Days == -4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(actual > TimeSpan.Zero);
|
||||
|
||||
Assert.True(actual.Seconds == 0 || actual.Seconds == 1);
|
||||
Assert.True(actual.Minutes == 0 || actual.Minutes == 2);
|
||||
Assert.True(actual.Hours == 0 || actual.Hours == 3);
|
||||
Assert.True(actual.Days == 0 || actual.Days == 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
179
test/Discord.Net.Tests.Unit/TokenUtilsTests.cs
Normal file
179
test/Discord.Net.Tests.Unit/TokenUtilsTests.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
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://discord.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]
|
||||
// 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);
|
||||
}
|
||||
}
|
60
test/Discord.Net.Tests/Tests.DiscordWebhookClient.cs
Normal file
60
test/Discord.Net.Tests/Tests.DiscordWebhookClient.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using Discord.Webhook;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests the <see cref="DiscordWebhookClient.ParseWebhookUrl(string, out ulong, out string)"/> function.
|
||||
/// </summary>
|
||||
public class DiscordWebhookClientTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("https://discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK",
|
||||
123412347732897802, "_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
// ptb, canary, etc will have slightly different urls
|
||||
[InlineData("https://ptb.discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK",
|
||||
123412347732897802, "_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
[InlineData("https://canary.discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK",
|
||||
123412347732897802, "_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
// don't care about https
|
||||
[InlineData("http://canary.discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK",
|
||||
123412347732897802, "_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
// this is the minimum that the regex cares about
|
||||
[InlineData("discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK",
|
||||
123412347732897802, "_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
public void TestWebhook_Valid(string webhookurl, ulong expectedId, string expectedToken)
|
||||
{
|
||||
DiscordWebhookClient.ParseWebhookUrl(webhookurl, out ulong id, out string token);
|
||||
|
||||
Assert.Equal(expectedId, id);
|
||||
Assert.Equal(expectedToken, token);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData(null)]
|
||||
public void TestWebhook_Null(string webhookurl)
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
{
|
||||
DiscordWebhookClient.ParseWebhookUrl(webhookurl, out ulong id, out string token);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK")]
|
||||
// trailing slash
|
||||
[InlineData("https://discord.com/api/webhooks/123412347732897802/_abcde123456789-ABCDEFGHIJKLMNOP12345678-abcdefghijklmnopABCDEFGHIJK/")]
|
||||
public void TestWebhook_Invalid(string webhookurl)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
DiscordWebhookClient.ParseWebhookUrl(webhookurl, out ulong id, out string token);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue