mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-22 10:55:15 -04:00
Clean up tests
This commit is contained in:
parent
301bca0633
commit
67313f2b22
10 changed files with 229 additions and 515 deletions
|
@ -5,6 +5,7 @@
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
<CollectCoverage>true</CollectCoverage>
|
<CollectCoverage>true</CollectCoverage>
|
||||||
<CoverletOutputFormat>opencover</CoverletOutputFormat>
|
<CoverletOutputFormat>opencover</CoverletOutputFormat>
|
||||||
|
<NoWarn>$(NoWarn);xUnit1013</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,69 +1,26 @@
|
||||||
using System;
|
using System.Linq;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
using CliFx.Infrastructure;
|
|
||||||
using DiscordChatExporter.Cli.Commands;
|
|
||||||
using DiscordChatExporter.Cli.Tests.Fixtures;
|
using DiscordChatExporter.Cli.Tests.Fixtures;
|
||||||
using DiscordChatExporter.Cli.Tests.Infra;
|
|
||||||
using DiscordChatExporter.Cli.Tests.TestData;
|
using DiscordChatExporter.Cli.Tests.TestData;
|
||||||
using DiscordChatExporter.Cli.Tests.Utils;
|
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Exporting;
|
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using JsonExtensions;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Tests
|
namespace DiscordChatExporter.Cli.Tests
|
||||||
{
|
{
|
||||||
public class EmbedSpecs : IClassFixture<TempOutputFixture>
|
public record EmbedSpecs(ExportWrapperFixture ExportWrapper) : IClassFixture<ExportWrapperFixture>
|
||||||
{
|
{
|
||||||
private readonly ITestOutputHelper _testOutput;
|
|
||||||
private readonly TempOutputFixture _tempOutput;
|
|
||||||
|
|
||||||
public EmbedSpecs(ITestOutputHelper testOutput, TempOutputFixture tempOutput)
|
|
||||||
{
|
|
||||||
_testOutput = testOutput;
|
|
||||||
_tempOutput = tempOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Message_with_an_embed_is_rendered_correctly_in_JSON()
|
public async Task Message_with_an_embed_is_rendered_correctly_in_JSON()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jsonData = await GlobalCache.WrapAsync("embed-specs-output-json", async () =>
|
var message = await ExportWrapper.GetMessageAsJsonAsync(
|
||||||
{
|
ChannelIds.EmbedTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866769910729146400")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.EmbedTestCases)},
|
|
||||||
ExportFormat = ExportFormat.Json,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
var embed = message
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(jsonData);
|
|
||||||
|
|
||||||
var json = Json.Parse(jsonData);
|
|
||||||
|
|
||||||
var messageJson = json
|
|
||||||
.GetProperty("messages")
|
|
||||||
.EnumerateArray()
|
|
||||||
.Single(j => string.Equals(
|
|
||||||
j.GetProperty("id").GetString(),
|
|
||||||
"866769910729146400",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
));
|
|
||||||
|
|
||||||
var embed = messageJson
|
|
||||||
.GetProperty("embeds")
|
.GetProperty("embeds")
|
||||||
.EnumerateArray()
|
.EnumerateArray()
|
||||||
.Single();
|
.Single();
|
||||||
|
@ -102,33 +59,14 @@ namespace DiscordChatExporter.Cli.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Message_with_an_embed_is_rendered_correctly_in_HTML()
|
public async Task Message_with_an_embed_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("embed-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.EmbedTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866769910729146400")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.EmbedTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866769910729146400");
|
|
||||||
var messageText = messageHtml?.Text();
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageText.Should().ContainAll(
|
message.Text().Should().ContainAll(
|
||||||
"Embed author",
|
"Embed author",
|
||||||
"Embed title",
|
"Embed title",
|
||||||
"Embed description",
|
"Embed description",
|
||||||
|
@ -142,30 +80,13 @@ namespace DiscordChatExporter.Cli.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Message_with_a_Spotify_track_is_rendered_using_an_iframe_in_HTML()
|
public async Task Message_with_a_Spotify_track_is_rendered_using_an_iframe_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("embed-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.EmbedTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("867886632203976775")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.EmbedTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
var iframeHtml = message.QuerySelector("iframe");
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-867886632203976775");
|
|
||||||
var iframeHtml = messageHtml?.QuerySelector("iframe");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
iframeHtml.Should().NotBeNull();
|
iframeHtml.Should().NotBeNull();
|
||||||
|
@ -176,30 +97,13 @@ namespace DiscordChatExporter.Cli.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Message_with_a_YouTube_video_is_rendered_using_an_iframe_in_HTML()
|
public async Task Message_with_a_YouTube_video_is_rendered_using_an_iframe_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("embed-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.EmbedTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866472508588294165")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.EmbedTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
var iframeHtml = message.QuerySelector("iframe");
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866472508588294165");
|
|
||||||
var iframeHtml = messageHtml?.QuerySelector("iframe");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
iframeHtml.Should().NotBeNull();
|
iframeHtml.Should().NotBeNull();
|
||||||
|
|
120
DiscordChatExporter.Cli.Tests/Fixtures/ExportWrapperFixture.cs
Normal file
120
DiscordChatExporter.Cli.Tests/Fixtures/ExportWrapperFixture.cs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AngleSharp.Dom;
|
||||||
|
using AngleSharp.Html.Dom;
|
||||||
|
using CliFx.Infrastructure;
|
||||||
|
using DiscordChatExporter.Cli.Commands;
|
||||||
|
using DiscordChatExporter.Cli.Tests.Infra;
|
||||||
|
using DiscordChatExporter.Cli.Tests.Utils;
|
||||||
|
using DiscordChatExporter.Core.Discord;
|
||||||
|
using DiscordChatExporter.Core.Exporting;
|
||||||
|
using JsonExtensions;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Cli.Tests.Fixtures
|
||||||
|
{
|
||||||
|
public class ExportWrapperFixture : IDisposable
|
||||||
|
{
|
||||||
|
private string DirPath { get; } = Path.Combine(
|
||||||
|
Path.GetDirectoryName(typeof(ExportWrapperFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(),
|
||||||
|
"ExportCache",
|
||||||
|
Guid.NewGuid().ToString()
|
||||||
|
);
|
||||||
|
|
||||||
|
public async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId)
|
||||||
|
{
|
||||||
|
var filePath = Path.Combine(DirPath, channelId + ".html");
|
||||||
|
|
||||||
|
// Perform export only if it hasn't been done before
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
await new ExportChannelsCommand
|
||||||
|
{
|
||||||
|
TokenValue = Secrets.DiscordToken,
|
||||||
|
IsBotToken = Secrets.IsDiscordTokenBot,
|
||||||
|
ChannelIds = new[] { channelId },
|
||||||
|
ExportFormat = ExportFormat.HtmlDark,
|
||||||
|
OutputPath = filePath
|
||||||
|
}.ExecuteAsync(new FakeConsole());
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = await File.ReadAllTextAsync(filePath);
|
||||||
|
|
||||||
|
return Html.Parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<IElement> GetMessageAsHtmlAsync(Snowflake channelId, Snowflake messageId)
|
||||||
|
{
|
||||||
|
var document = await ExportAsHtmlAsync(channelId);
|
||||||
|
|
||||||
|
var message = document.QuerySelector("#message-" + messageId);
|
||||||
|
|
||||||
|
if (message is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Message '{messageId}' does not exist in export of channel '{channelId}'."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<JsonElement> ExportAsJsonAsync(Snowflake channelId)
|
||||||
|
{
|
||||||
|
var filePath = Path.Combine(DirPath, channelId + ".json");
|
||||||
|
|
||||||
|
// Perform export only if it hasn't been done before
|
||||||
|
if (!File.Exists(filePath))
|
||||||
|
{
|
||||||
|
await new ExportChannelsCommand
|
||||||
|
{
|
||||||
|
TokenValue = Secrets.DiscordToken,
|
||||||
|
IsBotToken = Secrets.IsDiscordTokenBot,
|
||||||
|
ChannelIds = new[] { channelId },
|
||||||
|
ExportFormat = ExportFormat.Json,
|
||||||
|
OutputPath = filePath
|
||||||
|
}.ExecuteAsync(new FakeConsole());
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = await File.ReadAllTextAsync(filePath);
|
||||||
|
|
||||||
|
return Json.Parse(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<JsonElement> GetMessageAsJsonAsync(Snowflake channelId, Snowflake messageId)
|
||||||
|
{
|
||||||
|
var document = await ExportAsJsonAsync(channelId);
|
||||||
|
|
||||||
|
var message = document
|
||||||
|
.GetProperty("messages")
|
||||||
|
.EnumerateArray()
|
||||||
|
.SingleOrDefault(j => string.Equals(
|
||||||
|
j.GetProperty("id").GetString(),
|
||||||
|
messageId.ToString(),
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
));
|
||||||
|
|
||||||
|
if (message.ValueKind == JsonValueKind.Undefined)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Message '{messageId}' does not exist in export of channel '{channelId}'."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(DirPath, true);
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Tests.Fixtures
|
|
||||||
{
|
|
||||||
public class TempOutputFixture : IDisposable
|
|
||||||
{
|
|
||||||
public string DirPath => Path.Combine(
|
|
||||||
Path.GetDirectoryName(typeof(TempOutputFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(),
|
|
||||||
"Temp",
|
|
||||||
Guid.NewGuid().ToString()
|
|
||||||
);
|
|
||||||
|
|
||||||
public TempOutputFixture() => Directory.CreateDirectory(DirPath);
|
|
||||||
|
|
||||||
public string GetTempFilePath() => Path.Combine(DirPath, Guid.NewGuid().ToString());
|
|
||||||
|
|
||||||
public string GetTempFilePath(string extension) => Path.ChangeExtension(GetTempFilePath(), extension);
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(DirPath, true);
|
|
||||||
}
|
|
||||||
catch (DirectoryNotFoundException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +1,29 @@
|
||||||
using System;
|
using System.Linq;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
using CliFx.Infrastructure;
|
|
||||||
using DiscordChatExporter.Cli.Commands;
|
|
||||||
using DiscordChatExporter.Cli.Tests.Fixtures;
|
using DiscordChatExporter.Cli.Tests.Fixtures;
|
||||||
using DiscordChatExporter.Cli.Tests.Infra;
|
|
||||||
using DiscordChatExporter.Cli.Tests.TestData;
|
using DiscordChatExporter.Cli.Tests.TestData;
|
||||||
using DiscordChatExporter.Cli.Tests.Utils;
|
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Exporting;
|
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using JsonExtensions;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Tests
|
namespace DiscordChatExporter.Cli.Tests
|
||||||
{
|
{
|
||||||
public class MentionSpecs : IClassFixture<TempOutputFixture>
|
public record MentionSpecs(ExportWrapperFixture ExportWrapper) : IClassFixture<ExportWrapperFixture>
|
||||||
{
|
{
|
||||||
private readonly ITestOutputHelper _testOutput;
|
|
||||||
private readonly TempOutputFixture _tempOutput;
|
|
||||||
|
|
||||||
public MentionSpecs(ITestOutputHelper testOutput, TempOutputFixture tempOutput)
|
|
||||||
{
|
|
||||||
_testOutput = testOutput;
|
|
||||||
_tempOutput = tempOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task User_mention_is_rendered_correctly_in_JSON()
|
public async Task User_mention_is_rendered_correctly_in_JSON()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jsonData = await GlobalCache.WrapAsync("mention-specs-output-json", async () =>
|
var message = await ExportWrapper.GetMessageAsJsonAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866458840245076028")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.Json,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(jsonData);
|
|
||||||
|
|
||||||
var json = Json.Parse(jsonData);
|
|
||||||
|
|
||||||
var messageJson = json
|
|
||||||
.GetProperty("messages")
|
|
||||||
.EnumerateArray()
|
|
||||||
.Single(j => string.Equals(
|
|
||||||
j.GetProperty("id").GetString(),
|
|
||||||
"866458840245076028",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
));
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageJson.GetProperty("content").GetString().Should().Be("User mention: @Tyrrrz");
|
message.GetProperty("content").GetString().Should().Be("User mention: @Tyrrrz");
|
||||||
|
|
||||||
messageJson
|
message
|
||||||
.GetProperty("mentions")
|
.GetProperty("mentions")
|
||||||
.EnumerateArray()
|
.EnumerateArray()
|
||||||
.Select(j => j.GetProperty("id").GetString())
|
.Select(j => j.GetProperty("id").GetString())
|
||||||
|
@ -76,244 +33,93 @@ namespace DiscordChatExporter.Cli.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task User_mention_is_rendered_correctly_in_HTML()
|
public async Task User_mention_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("mention-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866458840245076028")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866458840245076028");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("User mention: @Tyrrrz");
|
||||||
messageHtml?.Text().Trim().Should().Be("User mention: @Tyrrrz");
|
message.InnerHtml.Should().Contain("Tyrrrz#5447");
|
||||||
messageHtml?.InnerHtml.Should().Contain("Tyrrrz#5447");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Text_channel_mention_is_rendered_correctly_in_JSON()
|
public async Task Text_channel_mention_is_rendered_correctly_in_JSON()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jsonData = await GlobalCache.WrapAsync("mention-specs-output-json", async () =>
|
var message = await ExportWrapper.GetMessageAsJsonAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459040480624680")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.Json,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(jsonData);
|
|
||||||
|
|
||||||
var json = Json.Parse(jsonData);
|
|
||||||
|
|
||||||
var messageJson = json
|
|
||||||
.GetProperty("messages")
|
|
||||||
.EnumerateArray()
|
|
||||||
.Single(j => string.Equals(
|
|
||||||
j.GetProperty("id").GetString(),
|
|
||||||
"866459040480624680",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
));
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageJson.GetProperty("content").GetString().Should().Be("Text channel mention: #mention-tests");
|
message.GetProperty("content").GetString().Should().Be("Text channel mention: #mention-tests");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Text_channel_mention_is_rendered_correctly_in_HTML()
|
public async Task Text_channel_mention_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("mention-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459040480624680")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866459040480624680");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("Text channel mention: #mention-tests");
|
||||||
messageHtml?.Text().Trim().Should().Be("Text channel mention: #mention-tests");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Voice_channel_mention_is_rendered_correctly_in_JSON()
|
public async Task Voice_channel_mention_is_rendered_correctly_in_JSON()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jsonData = await GlobalCache.WrapAsync("mention-specs-output-json", async () =>
|
var message = await ExportWrapper.GetMessageAsJsonAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459175462633503")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.Json,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(jsonData);
|
|
||||||
|
|
||||||
var json = Json.Parse(jsonData);
|
|
||||||
|
|
||||||
var messageJson = json
|
|
||||||
.GetProperty("messages")
|
|
||||||
.EnumerateArray()
|
|
||||||
.Single(j => string.Equals(
|
|
||||||
j.GetProperty("id").GetString(),
|
|
||||||
"866459175462633503",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
));
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageJson.GetProperty("content").GetString().Should().Be("Voice channel mention: #chaos-vc [voice]");
|
message.GetProperty("content").GetString().Should().Be("Voice channel mention: #chaos-vc [voice]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Voice_channel_mention_is_rendered_correctly_in_HTML()
|
public async Task Voice_channel_mention_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("mention-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459175462633503")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866459175462633503");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("Voice channel mention: 🔊chaos-vc");
|
||||||
messageHtml?.Text().Trim().Should().Be("Voice channel mention: 🔊chaos-vc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Role_mention_is_rendered_correctly_in_JSON()
|
public async Task Role_mention_is_rendered_correctly_in_JSON()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var jsonData = await GlobalCache.WrapAsync("mention-specs-output-json", async () =>
|
var message = await ExportWrapper.GetMessageAsJsonAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459254693429258")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.Json,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(jsonData);
|
|
||||||
|
|
||||||
var json = Json.Parse(jsonData);
|
|
||||||
|
|
||||||
var messageJson = json
|
|
||||||
.GetProperty("messages")
|
|
||||||
.EnumerateArray()
|
|
||||||
.Single(j => string.Equals(
|
|
||||||
j.GetProperty("id").GetString(),
|
|
||||||
"866459254693429258",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
));
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageJson.GetProperty("content").GetString().Should().Be("Role mention: @Role 1");
|
message.GetProperty("content").GetString().Should().Be("Role mention: @Role 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Role_mention_is_rendered_correctly_in_HTML()
|
public async Task Role_mention_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("mention-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.MentionTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866459254693429258")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.MentionTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866459254693429258");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("Role mention: @Role 1");
|
||||||
messageHtml?.Text().Trim().Should().Be("Role mention: @Role 1");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,129 +1,56 @@
|
||||||
using System.IO;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
using CliFx.Infrastructure;
|
|
||||||
using DiscordChatExporter.Cli.Commands;
|
|
||||||
using DiscordChatExporter.Cli.Tests.Fixtures;
|
using DiscordChatExporter.Cli.Tests.Fixtures;
|
||||||
using DiscordChatExporter.Cli.Tests.Infra;
|
|
||||||
using DiscordChatExporter.Cli.Tests.TestData;
|
using DiscordChatExporter.Cli.Tests.TestData;
|
||||||
using DiscordChatExporter.Cli.Tests.Utils;
|
|
||||||
using DiscordChatExporter.Core.Discord;
|
using DiscordChatExporter.Core.Discord;
|
||||||
using DiscordChatExporter.Core.Exporting;
|
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Tests
|
namespace DiscordChatExporter.Cli.Tests
|
||||||
{
|
{
|
||||||
public class ReplySpecs : IClassFixture<TempOutputFixture>
|
public record ReplySpecs(ExportWrapperFixture ExportWrapper) : IClassFixture<ExportWrapperFixture>
|
||||||
{
|
{
|
||||||
private readonly ITestOutputHelper _testOutput;
|
|
||||||
private readonly TempOutputFixture _tempOutput;
|
|
||||||
|
|
||||||
public ReplySpecs(ITestOutputHelper testOutput, TempOutputFixture tempOutput)
|
|
||||||
{
|
|
||||||
_testOutput = testOutput;
|
|
||||||
_tempOutput = tempOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Reply_to_a_normal_message_is_rendered_correctly_in_HTML()
|
public async Task Reply_to_a_normal_message_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("reply-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.ReplyTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866460738239725598")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.ReplyTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866460738239725598");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("reply to original");
|
||||||
messageHtml?.Text().Trim().Should().Be("reply to original");
|
message.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should().Be("original");
|
||||||
messageHtml?.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should().Be("original");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Reply_to_a_deleted_message_is_rendered_correctly_in_HTML()
|
public async Task Reply_to_a_deleted_message_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("reply-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.ReplyTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866460975388819486")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.ReplyTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866460975388819486");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("reply to deleted");
|
||||||
messageHtml?.Text().Trim().Should().Be("reply to deleted");
|
message.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should()
|
||||||
messageHtml?.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should()
|
|
||||||
.Be("Original message was deleted or could not be loaded.");
|
.Be("Original message was deleted or could not be loaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Reply_to_a_empty_message_with_attachment_is_rendered_correctly_in_HTML()
|
public async Task Reply_to_a_empty_message_with_attachment_is_rendered_correctly_in_HTML()
|
||||||
{
|
{
|
||||||
// Arrange
|
|
||||||
var outputFilePath = _tempOutput.GetTempFilePath("html");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var htmlData = await GlobalCache.WrapAsync("reply-specs-output-html", async () =>
|
var message = await ExportWrapper.GetMessageAsHtmlAsync(
|
||||||
{
|
ChannelIds.ReplyTestCases,
|
||||||
await new ExportChannelsCommand
|
Snowflake.Parse("866462470335627294")
|
||||||
{
|
);
|
||||||
TokenValue = Secrets.DiscordToken,
|
|
||||||
IsBotToken = Secrets.IsDiscordTokenBot,
|
|
||||||
ChannelIds = new[] {Snowflake.Parse(ChannelIds.ReplyTestCases)},
|
|
||||||
ExportFormat = ExportFormat.HtmlDark,
|
|
||||||
OutputPath = outputFilePath
|
|
||||||
}.ExecuteAsync(new FakeConsole());
|
|
||||||
|
|
||||||
return await File.ReadAllTextAsync(outputFilePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_testOutput.WriteLine(htmlData);
|
|
||||||
|
|
||||||
var html = Html.Parse(htmlData);
|
|
||||||
|
|
||||||
var messageHtml = html.QuerySelector("#message-866462470335627294");
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
messageHtml.Should().NotBeNull();
|
message.Text().Trim().Should().Be("reply to attachment");
|
||||||
messageHtml?.Text().Trim().Should().Be("reply to attachment");
|
message.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should()
|
||||||
messageHtml?.QuerySelector(".chatlog__reference-link")?.Text().Trim().Should()
|
|
||||||
.Be("Click to see attachment 🖼️");
|
.Be("Click to see attachment 🖼️");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
namespace DiscordChatExporter.Cli.Tests.TestData
|
using DiscordChatExporter.Core.Discord;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Cli.Tests.TestData
|
||||||
{
|
{
|
||||||
public static class ChannelIds
|
public static class ChannelIds
|
||||||
{
|
{
|
||||||
public static string EmbedTestCases => "866472452459462687";
|
public static Snowflake EmbedTestCases { get; } = Snowflake.Parse("866472452459462687");
|
||||||
|
|
||||||
public static string MentionTestCases => "866458801389174794";
|
public static Snowflake MentionTestCases { get; } = Snowflake.Parse("866458801389174794");
|
||||||
|
|
||||||
public static string ReplyTestCases => "866459871934677052";
|
public static Snowflake ReplyTestCases { get; } = Snowflake.Parse("866459871934677052");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DiscordChatExporter.Cli.Tests.Utils
|
|
||||||
{
|
|
||||||
internal static class GlobalCache
|
|
||||||
{
|
|
||||||
private static readonly ConcurrentDictionary<string, object?> Dictionary = new();
|
|
||||||
|
|
||||||
public static async Task<T> WrapAsync<T>(string key, Func<Task<T>> getAsync)
|
|
||||||
{
|
|
||||||
if (Dictionary.TryGetValue(key, out var value) && value is T existing)
|
|
||||||
return existing;
|
|
||||||
|
|
||||||
var result = await getAsync();
|
|
||||||
Dictionary[key] = result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
9
DiscordChatExporter.Cli.Tests/Utils/Pollyfills.cs
Normal file
9
DiscordChatExporter.Cli.Tests/Utils/Pollyfills.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
// TODO: remove after moving to .NET 5
|
||||||
|
|
||||||
|
namespace System.Runtime.CompilerServices
|
||||||
|
{
|
||||||
|
internal static class IsExternalInit
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,15 +22,13 @@ namespace DiscordChatExporter.Cli.Utils.Extensions
|
||||||
? new NoopExclusivityMode()
|
? new NoopExclusivityMode()
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return AnsiConsole.Create(
|
return AnsiConsole.Create(new AnsiConsoleSettings
|
||||||
new AnsiConsoleSettings
|
{
|
||||||
{
|
Ansi = AnsiSupport.Detect,
|
||||||
Ansi = AnsiSupport.Detect,
|
ColorSystem = ColorSystemSupport.Detect,
|
||||||
ColorSystem = ColorSystemSupport.Detect,
|
Out = new AnsiConsoleOutput(console.Output),
|
||||||
Out = new AnsiConsoleOutput(console.Output),
|
ExclusivityMode = exclusivityMode
|
||||||
ExclusivityMode = exclusivityMode
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Progress CreateProgressTicker(this IConsole console) => console
|
public static Progress CreateProgressTicker(this IConsole console) => console
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue