Get rid of xUnit fixtures

This commit is contained in:
Tyrrrz 2023-02-11 23:12:15 +02:00
parent 3487849eba
commit 53b8927fce
29 changed files with 221 additions and 347 deletions

View file

@ -1,8 +0,0 @@
using Xunit;
namespace DiscordChatExporter.Cli.Tests.Fixtures;
[CollectionDefinition(nameof(ExportWrapperCollection))]
public class ExportWrapperCollection : ICollectionFixture<ExportWrapperFixture>
{
}

View file

@ -1,22 +0,0 @@
using System;
using System.IO;
using DiscordChatExporter.Cli.Tests.Utils;
namespace DiscordChatExporter.Cli.Tests.Fixtures;
public class TempOutputFixture : IDisposable
{
public string DirPath { get; } = Path.Combine(
Path.GetDirectoryName(typeof(TempOutputFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(),
"Temp",
Guid.NewGuid().ToString()
);
public TempOutputFixture() => DirectoryEx.Reset(DirPath);
public string GetTempFilePath(string fileName) => Path.Combine(DirPath, fileName);
public string GetTempFilePath() => GetTempFilePath(Guid.NewGuid() + ".tmp");
public void Dispose() => DirectoryEx.DeleteIfExists(DirPath);
}

View file

@ -2,31 +2,34 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using AngleSharp.Html.Dom; using AngleSharp.Html.Dom;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.Utils; using DiscordChatExporter.Cli.Tests.Utils;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using DiscordChatExporter.Core.Exporting; using DiscordChatExporter.Core.Exporting;
using JsonExtensions; using JsonExtensions;
namespace DiscordChatExporter.Cli.Tests.Fixtures; namespace DiscordChatExporter.Cli.Tests.Infra;
public class ExportWrapperFixture : IDisposable public static class ExportWrapper
{ {
private string DirPath { get; } = Path.Combine( private static readonly string DirPath = Path.Combine(
Path.GetDirectoryName(typeof(ExportWrapperFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(), Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory(),
"ExportCache", "ExportCache"
Guid.NewGuid().ToString()
); );
public ExportWrapperFixture() => DirectoryEx.Reset(DirPath); static ExportWrapper()
{
Directory.Delete(DirPath, true);
Directory.CreateDirectory(DirPath);
}
private async ValueTask<string> ExportAsync(Snowflake channelId, ExportFormat format) private static async ValueTask<string> ExportAsync(Snowflake channelId, ExportFormat format)
{ {
var fileName = channelId.ToString() + '.' + format.GetFileExtension(); var fileName = channelId.ToString() + '.' + format.GetFileExtension();
var filePath = Path.Combine(DirPath, fileName); var filePath = Path.Combine(DirPath, fileName);
@ -55,32 +58,32 @@ public class ExportWrapperFixture : IDisposable
return await File.ReadAllTextAsync(filePath); return await File.ReadAllTextAsync(filePath);
} }
public async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse( public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) => Html.Parse(
await ExportAsync(channelId, ExportFormat.HtmlDark) await ExportAsync(channelId, ExportFormat.HtmlDark)
); );
public async ValueTask<JsonElement> ExportAsJsonAsync(Snowflake channelId) => Json.Parse( public static async ValueTask<JsonElement> ExportAsJsonAsync(Snowflake channelId) => Json.Parse(
await ExportAsync(channelId, ExportFormat.Json) await ExportAsync(channelId, ExportFormat.Json)
); );
public async ValueTask<string> ExportAsPlainTextAsync(Snowflake channelId) => public static async ValueTask<string> ExportAsPlainTextAsync(Snowflake channelId) =>
await ExportAsync(channelId, ExportFormat.PlainText); await ExportAsync(channelId, ExportFormat.PlainText);
public async ValueTask<string> ExportAsCsvAsync(Snowflake channelId) => public static async ValueTask<string> ExportAsCsvAsync(Snowflake channelId) =>
await ExportAsync(channelId, ExportFormat.Csv); await ExportAsync(channelId, ExportFormat.Csv);
public async ValueTask<IReadOnlyList<IElement>> GetMessagesAsHtmlAsync(Snowflake channelId) => public static async ValueTask<IReadOnlyList<IElement>> GetMessagesAsHtmlAsync(Snowflake channelId) =>
(await ExportAsHtmlAsync(channelId)) (await ExportAsHtmlAsync(channelId))
.QuerySelectorAll("[data-message-id]") .QuerySelectorAll("[data-message-id]")
.ToArray(); .ToArray();
public async ValueTask<IReadOnlyList<JsonElement>> GetMessagesAsJsonAsync(Snowflake channelId) => public static async ValueTask<IReadOnlyList<JsonElement>> GetMessagesAsJsonAsync(Snowflake channelId) =>
(await ExportAsJsonAsync(channelId)) (await ExportAsJsonAsync(channelId))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.ToArray(); .ToArray();
public async ValueTask<IElement> GetMessageAsHtmlAsync(Snowflake channelId, Snowflake messageId) public static async ValueTask<IElement> GetMessageAsHtmlAsync(Snowflake channelId, Snowflake messageId)
{ {
var message = (await GetMessagesAsHtmlAsync(channelId)) var message = (await GetMessagesAsHtmlAsync(channelId))
.SingleOrDefault(e => .SingleOrDefault(e =>
@ -101,7 +104,7 @@ public class ExportWrapperFixture : IDisposable
return message; return message;
} }
public async ValueTask<JsonElement> GetMessageAsJsonAsync(Snowflake channelId, Snowflake messageId) public static async ValueTask<JsonElement> GetMessageAsJsonAsync(Snowflake channelId, Snowflake messageId)
{ {
var message = (await GetMessagesAsJsonAsync(channelId)) var message = (await GetMessagesAsJsonAsync(channelId))
.SingleOrDefault(j => .SingleOrDefault(j =>
@ -121,6 +124,4 @@ public class ExportWrapperFixture : IDisposable
return message; return message;
} }
public void Dispose() => DirectoryEx.DeleteIfExists(DirPath);
} }

View file

@ -1,26 +1,18 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class CsvContentSpecs public class CsvContentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public CsvContentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Messages_are_exported_correctly() public async Task Messages_are_exported_correctly()
{ {
// Act // Act
var document = await _exportWrapper.ExportAsCsvAsync(ChannelIds.DateRangeTestCases); var document = await ExportWrapper.ExportAsCsvAsync(ChannelIds.DateRangeTestCases);
// Assert // Assert
document.Should().ContainAll( document.Should().ContainAll(

View file

@ -4,9 +4,9 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Fixtures;
using DiscordChatExporter.Cli.Tests.Infra; 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 DiscordChatExporter.Core.Exporting;
using FluentAssertions; using FluentAssertions;
@ -15,22 +15,14 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))] public class DateRangeSpecs
public class DateRangeSpecs : IClassFixture<TempOutputFixture>
{ {
private readonly TempOutputFixture _tempOutput;
public DateRangeSpecs(TempOutputFixture tempOutput)
{
_tempOutput = tempOutput;
}
[Fact] [Fact]
public async Task Messages_filtered_after_specific_date_only_include_messages_sent_after_that_date() public async Task Messages_filtered_after_specific_date_only_include_messages_sent_after_that_date()
{ {
// Arrange // Arrange
var after = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero); var after = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero);
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -38,13 +30,13 @@ public class DateRangeSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.DateRangeTestCases }, ChannelIds = new[] { ChannelIds.DateRangeTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
After = Snowflake.FromDate(after) After = Snowflake.FromDate(after)
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
var timestamps = Json var timestamps = Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("timestamp").GetDateTimeOffset()) .Select(j => j.GetProperty("timestamp").GetDateTimeOffset())
@ -74,7 +66,7 @@ public class DateRangeSpecs : IClassFixture<TempOutputFixture>
{ {
// Arrange // Arrange
var before = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero); var before = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero);
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -82,13 +74,13 @@ public class DateRangeSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.DateRangeTestCases }, ChannelIds = new[] { ChannelIds.DateRangeTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
Before = Snowflake.FromDate(before) Before = Snowflake.FromDate(before)
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
var timestamps = Json var timestamps = Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("timestamp").GetDateTimeOffset()) .Select(j => j.GetProperty("timestamp").GetDateTimeOffset())
@ -117,7 +109,7 @@ public class DateRangeSpecs : IClassFixture<TempOutputFixture>
// Arrange // Arrange
var after = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero); var after = new DateTimeOffset(2021, 07, 24, 0, 0, 0, TimeSpan.Zero);
var before = new DateTimeOffset(2021, 08, 01, 0, 0, 0, TimeSpan.Zero); var before = new DateTimeOffset(2021, 08, 01, 0, 0, 0, TimeSpan.Zero);
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -125,14 +117,14 @@ public class DateRangeSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.DateRangeTestCases }, ChannelIds = new[] { ChannelIds.DateRangeTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
Before = Snowflake.FromDate(before), Before = Snowflake.FromDate(before),
After = Snowflake.FromDate(after) After = Snowflake.FromDate(after)
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
var timestamps = Json var timestamps = Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("timestamp").GetDateTimeOffset()) .Select(j => j.GetProperty("timestamp").GetDateTimeOffset())

View file

@ -3,9 +3,9 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Fixtures;
using DiscordChatExporter.Cli.Tests.Infra; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Cli.Tests.Utils;
using DiscordChatExporter.Core.Exporting; using DiscordChatExporter.Core.Exporting;
using DiscordChatExporter.Core.Exporting.Filtering; using DiscordChatExporter.Core.Exporting.Filtering;
using FluentAssertions; using FluentAssertions;
@ -14,21 +14,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))] public class FilterSpecs
public class FilterSpecs : IClassFixture<TempOutputFixture>
{ {
private readonly TempOutputFixture _tempOutput;
public FilterSpecs(TempOutputFixture tempOutput)
{
_tempOutput = tempOutput;
}
[Fact] [Fact]
public async Task Messages_filtered_by_text_only_include_messages_that_contain_that_text() public async Task Messages_filtered_by_text_only_include_messages_that_contain_that_text()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -36,13 +28,13 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.FilterTestCases }, ChannelIds = new[] { ChannelIds.FilterTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
MessageFilter = MessageFilter.Parse("some text") MessageFilter = MessageFilter.Parse("some text")
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Json Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("content").GetString()) .Select(j => j.GetProperty("content").GetString())
@ -54,7 +46,7 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
public async Task Messages_filtered_by_author_only_include_messages_sent_by_that_author() public async Task Messages_filtered_by_author_only_include_messages_sent_by_that_author()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -62,13 +54,13 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.FilterTestCases }, ChannelIds = new[] { ChannelIds.FilterTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
MessageFilter = MessageFilter.Parse("from:Tyrrrz") MessageFilter = MessageFilter.Parse("from:Tyrrrz")
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Json Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("author").GetProperty("name").GetString()) .Select(j => j.GetProperty("author").GetProperty("name").GetString())
@ -80,7 +72,7 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
public async Task Messages_filtered_by_content_only_include_messages_that_have_that_content() public async Task Messages_filtered_by_content_only_include_messages_that_have_that_content()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -88,13 +80,13 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.FilterTestCases }, ChannelIds = new[] { ChannelIds.FilterTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
MessageFilter = MessageFilter.Parse("has:image") MessageFilter = MessageFilter.Parse("has:image")
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Json Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("content").GetString()) .Select(j => j.GetProperty("content").GetString())
@ -106,7 +98,7 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
public async Task Messages_filtered_by_pin_only_include_messages_that_have_been_pinned() public async Task Messages_filtered_by_pin_only_include_messages_that_have_been_pinned()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -114,13 +106,13 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.FilterTestCases }, ChannelIds = new[] { ChannelIds.FilterTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
MessageFilter = MessageFilter.Parse("has:pin") MessageFilter = MessageFilter.Parse("has:pin")
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Json Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("content").GetString()) .Select(j => j.GetProperty("content").GetString())
@ -132,7 +124,7 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
public async Task Messages_filtered_by_mention_only_include_messages_that_have_that_mention() public async Task Messages_filtered_by_mention_only_include_messages_that_have_that_mention()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -140,13 +132,13 @@ public class FilterSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.FilterTestCases }, ChannelIds = new[] { ChannelIds.FilterTestCases },
ExportFormat = ExportFormat.Json, ExportFormat = ExportFormat.Json,
OutputPath = filePath, OutputPath = file.Path,
MessageFilter = MessageFilter.Parse("mentions:Tyrrrz") MessageFilter = MessageFilter.Parse("mentions:Tyrrrz")
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Json Json
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.GetProperty("messages") .GetProperty("messages")
.EnumerateArray() .EnumerateArray()
.Select(j => j.GetProperty("content").GetString()) .Select(j => j.GetProperty("content").GetString())

View file

@ -1,7 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -9,21 +9,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlAttachmentSpecs public class HtmlAttachmentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlAttachmentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_a_generic_attachment_is_rendered_correctly() public async Task Message_with_a_generic_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885587844989612074") Snowflake.Parse("885587844989612074")
); );
@ -48,7 +40,7 @@ public class HtmlAttachmentSpecs
public async Task Message_with_an_image_attachment_is_rendered_correctly() public async Task Message_with_an_image_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885654862656843786") Snowflake.Parse("885654862656843786")
); );
@ -71,7 +63,7 @@ public class HtmlAttachmentSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/333 // https://github.com/Tyrrrz/DiscordChatExporter/issues/333
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885655761919836171") Snowflake.Parse("885655761919836171")
); );
@ -91,7 +83,7 @@ public class HtmlAttachmentSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/333 // https://github.com/Tyrrrz/DiscordChatExporter/issues/333
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885656175620808734") Snowflake.Parse("885656175620808734")
); );

View file

@ -1,7 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -9,21 +9,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlContentSpecs public class HtmlContentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlContentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Messages_are_exported_correctly() public async Task Messages_are_exported_correctly()
{ {
// Act // Act
var messages = await _exportWrapper.GetMessagesAsHtmlAsync(ChannelIds.DateRangeTestCases); var messages = await ExportWrapper.GetMessagesAsHtmlAsync(ChannelIds.DateRangeTestCases);
// Assert // Assert
messages.Select(e => e.GetAttribute("data-message-id")).Should().Equal( messages.Select(e => e.GetAttribute("data-message-id")).Should().Equal(
@ -55,7 +47,7 @@ public class HtmlContentSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/633 // https://github.com/Tyrrrz/DiscordChatExporter/issues/633
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.ReplyTestCases, ChannelIds.ReplyTestCases,
Snowflake.Parse("1072165330853576876") Snowflake.Parse("1072165330853576876")
); );

View file

@ -1,7 +1,7 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -9,21 +9,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlEmbedSpecs public class HtmlEmbedSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlEmbedSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_an_embed_is_rendered_correctly() public async Task Message_with_an_embed_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("866769910729146400") Snowflake.Parse("866769910729146400")
); );
@ -46,7 +38,7 @@ public class HtmlEmbedSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/537 // https://github.com/Tyrrrz/DiscordChatExporter/issues/537
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("991768701126852638") Snowflake.Parse("991768701126852638")
); );
@ -66,7 +58,7 @@ public class HtmlEmbedSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/682 // https://github.com/Tyrrrz/DiscordChatExporter/issues/682
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("991768701126852638") Snowflake.Parse("991768701126852638")
); );
@ -80,7 +72,7 @@ public class HtmlEmbedSpecs
public async Task Message_containing_a_gifv_link_is_rendered_with_a_video_embed() public async Task Message_containing_a_gifv_link_is_rendered_with_a_video_embed()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("1019234520349814794") Snowflake.Parse("1019234520349814794")
); );
@ -98,7 +90,7 @@ public class HtmlEmbedSpecs
public async Task Message_containing_a_gifv_link_and_nothing_else_is_rendered_without_text_content() public async Task Message_containing_a_gifv_link_and_nothing_else_is_rendered_without_text_content()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("1019234520349814794") Snowflake.Parse("1019234520349814794")
); );
@ -114,7 +106,7 @@ public class HtmlEmbedSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/657 // https://github.com/Tyrrrz/DiscordChatExporter/issues/657
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("867886632203976775") Snowflake.Parse("867886632203976775")
); );
@ -130,7 +122,7 @@ public class HtmlEmbedSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/570 // https://github.com/Tyrrrz/DiscordChatExporter/issues/570
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("866472508588294165") Snowflake.Parse("866472508588294165")
); );
@ -146,7 +138,7 @@ public class HtmlEmbedSpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/695 // https://github.com/Tyrrrz/DiscordChatExporter/issues/695
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("991757444017557665") Snowflake.Parse("991757444017557665")
); );

View file

@ -4,32 +4,24 @@ using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Fixtures;
using DiscordChatExporter.Cli.Tests.Infra; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Cli.Tests.Utils;
using DiscordChatExporter.Core.Exporting; using DiscordChatExporter.Core.Exporting;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))] public class HtmlGroupingSpecs
public class HtmlGroupingSpecs : IClassFixture<TempOutputFixture>
{ {
private readonly TempOutputFixture _tempOutput;
public HtmlGroupingSpecs(TempOutputFixture tempOutput)
{
_tempOutput = tempOutput;
}
[Fact] [Fact]
public async Task Messages_are_grouped_correctly() public async Task Messages_are_grouped_correctly()
{ {
// https://github.com/Tyrrrz/DiscordChatExporter/issues/152 // https://github.com/Tyrrrz/DiscordChatExporter/issues/152
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var file = TempFile.Create();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -37,12 +29,12 @@ public class HtmlGroupingSpecs : IClassFixture<TempOutputFixture>
Token = Secrets.DiscordToken, Token = Secrets.DiscordToken,
ChannelIds = new[] { ChannelIds.GroupingTestCases }, ChannelIds = new[] { ChannelIds.GroupingTestCases },
ExportFormat = ExportFormat.HtmlDark, ExportFormat = ExportFormat.HtmlDark,
OutputPath = filePath OutputPath = file.Path
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
var messageGroups = Utils.Html var messageGroups = Html
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(file.Path))
.QuerySelectorAll(".chatlog__message-group"); .QuerySelectorAll(".chatlog__message-group");
messageGroups.Should().HaveCount(2); messageGroups.Should().HaveCount(2);

View file

@ -1,6 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlMentionSpecs public class HtmlMentionSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlMentionSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task User_mention_is_rendered_correctly() public async Task User_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866458840245076028") Snowflake.Parse("866458840245076028")
); );
@ -36,7 +28,7 @@ public class HtmlMentionSpecs
public async Task Text_channel_mention_is_rendered_correctly() public async Task Text_channel_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459040480624680") Snowflake.Parse("866459040480624680")
); );
@ -49,7 +41,7 @@ public class HtmlMentionSpecs
public async Task Voice_channel_mention_is_rendered_correctly() public async Task Voice_channel_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459175462633503") Snowflake.Parse("866459175462633503")
); );
@ -62,7 +54,7 @@ public class HtmlMentionSpecs
public async Task Role_mention_is_rendered_correctly() public async Task Role_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459254693429258") Snowflake.Parse("866459254693429258")
); );

View file

@ -1,6 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using AngleSharp.Dom; using AngleSharp.Dom;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlReplySpecs public class HtmlReplySpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlReplySpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Reply_to_a_normal_message_is_rendered_correctly() public async Task Reply_to_a_normal_message_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.ReplyTestCases, ChannelIds.ReplyTestCases,
Snowflake.Parse("866460738239725598") Snowflake.Parse("866460738239725598")
); );
@ -38,7 +30,7 @@ public class HtmlReplySpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/645 // https://github.com/Tyrrrz/DiscordChatExporter/issues/645
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.ReplyTestCases, ChannelIds.ReplyTestCases,
Snowflake.Parse("866460975388819486") Snowflake.Parse("866460975388819486")
); );
@ -56,7 +48,7 @@ public class HtmlReplySpecs
// https://github.com/Tyrrrz/DiscordChatExporter/issues/634 // https://github.com/Tyrrrz/DiscordChatExporter/issues/634
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.ReplyTestCases, ChannelIds.ReplyTestCases,
Snowflake.Parse("866462470335627294") Snowflake.Parse("866462470335627294")
); );

View file

@ -1,5 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -7,21 +7,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class HtmlStickerSpecs public class HtmlStickerSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public HtmlStickerSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_a_PNG_based_sticker_is_rendered_correctly() public async Task Message_with_a_PNG_based_sticker_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.StickerTestCases, ChannelIds.StickerTestCases,
Snowflake.Parse("939670623158943754") Snowflake.Parse("939670623158943754")
); );
@ -35,7 +27,7 @@ public class HtmlStickerSpecs
public async Task Message_with_a_Lottie_based_sticker_is_rendered_correctly() public async Task Message_with_a_Lottie_based_sticker_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsHtmlAsync( var message = await ExportWrapper.GetMessageAsHtmlAsync(
ChannelIds.StickerTestCases, ChannelIds.StickerTestCases,
Snowflake.Parse("939670526517997590") Snowflake.Parse("939670526517997590")
); );

View file

@ -1,6 +1,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class JsonAttachmentSpecs public class JsonAttachmentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public JsonAttachmentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_a_generic_attachment_is_rendered_correctly() public async Task Message_with_a_generic_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885587844989612074") Snowflake.Parse("885587844989612074")
); );
@ -43,7 +35,7 @@ public class JsonAttachmentSpecs
public async Task Message_with_an_image_attachment_is_rendered_correctly() public async Task Message_with_an_image_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885654862656843786") Snowflake.Parse("885654862656843786")
); );
@ -64,7 +56,7 @@ public class JsonAttachmentSpecs
public async Task Message_with_a_video_attachment_is_rendered_correctly() public async Task Message_with_a_video_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885655761919836171") Snowflake.Parse("885655761919836171")
); );
@ -85,7 +77,7 @@ public class JsonAttachmentSpecs
public async Task Message_with_an_audio_attachment_is_rendered_correctly() public async Task Message_with_an_audio_attachment_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.AttachmentTestCases, ChannelIds.AttachmentTestCases,
Snowflake.Parse("885656175620808734") Snowflake.Parse("885656175620808734")
); );

View file

@ -1,27 +1,19 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class JsonContentSpecs public class JsonContentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public JsonContentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Messages_are_exported_correctly() public async Task Messages_are_exported_correctly()
{ {
// Act // Act
var messages = await _exportWrapper.GetMessagesAsJsonAsync(ChannelIds.DateRangeTestCases); var messages = await ExportWrapper.GetMessagesAsJsonAsync(ChannelIds.DateRangeTestCases);
// Assert // Assert
messages.Select(j => j.GetProperty("id").GetString()).Should().Equal( messages.Select(j => j.GetProperty("id").GetString()).Should().Equal(

View file

@ -1,6 +1,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class JsonEmbedSpecs public class JsonEmbedSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public JsonEmbedSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_an_embed_is_rendered_correctly() public async Task Message_with_an_embed_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.EmbedTestCases, ChannelIds.EmbedTestCases,
Snowflake.Parse("866769910729146400") Snowflake.Parse("866769910729146400")
); );

View file

@ -1,6 +1,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class JsonMentionSpecs public class JsonMentionSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public JsonMentionSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task User_mention_is_rendered_correctly() public async Task User_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866458840245076028") Snowflake.Parse("866458840245076028")
); );
@ -42,7 +34,7 @@ public class JsonMentionSpecs
public async Task Text_channel_mention_is_rendered_correctly() public async Task Text_channel_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459040480624680") Snowflake.Parse("866459040480624680")
); );
@ -55,7 +47,7 @@ public class JsonMentionSpecs
public async Task Voice_channel_mention_is_rendered_correctly() public async Task Voice_channel_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459175462633503") Snowflake.Parse("866459175462633503")
); );
@ -68,7 +60,7 @@ public class JsonMentionSpecs
public async Task Role_mention_is_rendered_correctly() public async Task Role_mention_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.MentionTestCases, ChannelIds.MentionTestCases,
Snowflake.Parse("866459254693429258") Snowflake.Parse("866459254693429258")
); );

View file

@ -1,6 +1,6 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord;
using FluentAssertions; using FluentAssertions;
@ -8,21 +8,13 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class JsonStickerSpecs public class JsonStickerSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public JsonStickerSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Message_with_a_PNG_based_sticker_is_rendered_correctly() public async Task Message_with_a_PNG_based_sticker_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.StickerTestCases, ChannelIds.StickerTestCases,
Snowflake.Parse("939670623158943754") Snowflake.Parse("939670623158943754")
); );
@ -43,7 +35,7 @@ public class JsonStickerSpecs
public async Task Message_with_a_Lottie_based_sticker_is_rendered_correctly() public async Task Message_with_a_Lottie_based_sticker_is_rendered_correctly()
{ {
// Act // Act
var message = await _exportWrapper.GetMessageAsJsonAsync( var message = await ExportWrapper.GetMessageAsJsonAsync(
ChannelIds.StickerTestCases, ChannelIds.StickerTestCases,
Snowflake.Parse("939670526517997590") Snowflake.Parse("939670526517997590")
); );

View file

@ -2,9 +2,9 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Fixtures;
using DiscordChatExporter.Cli.Tests.Infra; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Cli.Tests.Utils;
using DiscordChatExporter.Core.Exporting; using DiscordChatExporter.Core.Exporting;
using DiscordChatExporter.Core.Exporting.Partitioning; using DiscordChatExporter.Core.Exporting.Partitioning;
using FluentAssertions; using FluentAssertions;
@ -12,23 +12,14 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))] public class PartitioningSpecs
public class PartitioningSpecs : IClassFixture<TempOutputFixture>
{ {
private readonly TempOutputFixture _tempOutput;
public PartitioningSpecs(TempOutputFixture tempOutput)
{
_tempOutput = tempOutput;
}
[Fact] [Fact]
public async Task Messages_partitioned_by_count_are_split_into_a_corresponding_number_of_files() public async Task Messages_partitioned_by_count_are_split_into_a_corresponding_number_of_files()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var dir = TempDir.Create();
var fileNameWithoutExt = Path.GetFileNameWithoutExtension(filePath); var filePath = Path.Combine(dir.Path, "output.html");
var dirPath = Path.GetDirectoryName(filePath) ?? Directory.GetCurrentDirectory();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -41,7 +32,7 @@ public class PartitioningSpecs : IClassFixture<TempOutputFixture>
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Directory.EnumerateFiles(dirPath, fileNameWithoutExt + "*") Directory.EnumerateFiles(dir.Path, "output*")
.Should() .Should()
.HaveCount(3); .HaveCount(3);
} }
@ -50,9 +41,8 @@ public class PartitioningSpecs : IClassFixture<TempOutputFixture>
public async Task Messages_partitioned_by_file_size_are_split_into_a_corresponding_number_of_files() public async Task Messages_partitioned_by_file_size_are_split_into_a_corresponding_number_of_files()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var dir = TempDir.Create();
var fileNameWithoutExt = Path.GetFileNameWithoutExtension(filePath); var filePath = Path.Combine(dir.Path, "output.html");
var dirPath = Path.GetDirectoryName(filePath) ?? Directory.GetCurrentDirectory();
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -65,7 +55,7 @@ public class PartitioningSpecs : IClassFixture<TempOutputFixture>
}.ExecuteAsync(new FakeConsole()); }.ExecuteAsync(new FakeConsole());
// Assert // Assert
Directory.EnumerateFiles(dirPath, fileNameWithoutExt + "*") Directory.EnumerateFiles(dir.Path, "output*")
.Should() .Should()
.HaveCount(8); .HaveCount(8);
} }

View file

@ -1,26 +1,18 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using DiscordChatExporter.Cli.Tests.Fixtures; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))]
public class PlainTextContentSpecs public class PlainTextContentSpecs
{ {
private readonly ExportWrapperFixture _exportWrapper;
public PlainTextContentSpecs(ExportWrapperFixture exportWrapper)
{
_exportWrapper = exportWrapper;
}
[Fact] [Fact]
public async Task Messages_are_exported_correctly() public async Task Messages_are_exported_correctly()
{ {
// Act // Act
var document = await _exportWrapper.ExportAsPlainTextAsync(ChannelIds.DateRangeTestCases); var document = await ExportWrapper.ExportAsPlainTextAsync(ChannelIds.DateRangeTestCases);
// Assert // Assert
document.Should().ContainAll( document.Should().ContainAll(

View file

@ -3,7 +3,6 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CliFx.Infrastructure; using CliFx.Infrastructure;
using DiscordChatExporter.Cli.Commands; using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Tests.Fixtures;
using DiscordChatExporter.Cli.Tests.Infra; using DiscordChatExporter.Cli.Tests.Infra;
using DiscordChatExporter.Cli.Tests.TestData; using DiscordChatExporter.Cli.Tests.TestData;
using DiscordChatExporter.Cli.Tests.Utils; using DiscordChatExporter.Cli.Tests.Utils;
@ -13,22 +12,14 @@ using Xunit;
namespace DiscordChatExporter.Cli.Tests.Specs; namespace DiscordChatExporter.Cli.Tests.Specs;
[Collection(nameof(ExportWrapperCollection))] public class SelfContainedSpecs
public class SelfContainedSpecs : IClassFixture<TempOutputFixture>
{ {
private readonly TempOutputFixture _tempOutput;
public SelfContainedSpecs(TempOutputFixture tempOutput)
{
_tempOutput = tempOutput;
}
[Fact] [Fact]
public async Task Messages_in_self_contained_export_only_reference_local_file_resources() public async Task Messages_in_self_contained_export_only_reference_local_file_resources()
{ {
// Arrange // Arrange
var filePath = _tempOutput.GetTempFilePath(); using var dir = TempDir.Create();
var dirPath = Path.GetDirectoryName(filePath) ?? Directory.GetCurrentDirectory(); var filePath = Path.Combine(dir.Path, "output.html");
// Act // Act
await new ExportChannelsCommand await new ExportChannelsCommand
@ -45,7 +36,7 @@ public class SelfContainedSpecs : IClassFixture<TempOutputFixture>
.Parse(await File.ReadAllTextAsync(filePath)) .Parse(await File.ReadAllTextAsync(filePath))
.QuerySelectorAll("body [src]") .QuerySelectorAll("body [src]")
.Select(e => e.GetAttribute("src")!) .Select(e => e.GetAttribute("src")!)
.Select(f => Path.GetFullPath(f, dirPath)) .Select(f => Path.GetFullPath(f, dir.Path))
.All(File.Exists) .All(File.Exists)
.Should() .Should()
.BeTrue(); .BeTrue();

View file

@ -1,23 +0,0 @@
using System.IO;
namespace DiscordChatExporter.Cli.Tests.Utils;
internal static class DirectoryEx
{
public static void DeleteIfExists(string dirPath, bool recursive = true)
{
try
{
Directory.Delete(dirPath, recursive);
}
catch (DirectoryNotFoundException)
{
}
}
public static void Reset(string dirPath)
{
DeleteIfExists(dirPath);
Directory.CreateDirectory(dirPath);
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.IO;
using System.Reflection;
using PathEx = System.IO.Path;
namespace DiscordChatExporter.Cli.Tests.Utils;
internal partial class TempDir : IDisposable
{
public string Path { get; }
public TempDir(string path) =>
Path = path;
public void Dispose()
{
try
{
Directory.Delete(Path, true);
}
catch (DirectoryNotFoundException)
{
}
}
}
internal partial class TempDir
{
public static TempDir Create()
{
var dirPath = PathEx.Combine(
PathEx.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory(),
"Temp",
Guid.NewGuid().ToString()
);
Directory.CreateDirectory(dirPath);
return new TempDir(dirPath);
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Reflection;
using PathEx = System.IO.Path;
namespace DiscordChatExporter.Cli.Tests.Utils;
internal partial class TempFile : IDisposable
{
public string Path { get; }
public TempFile(string path) =>
Path = path;
public void Dispose()
{
try
{
File.Delete(Path);
}
catch (FileNotFoundException)
{
}
}
}
internal partial class TempFile
{
public static TempFile Create()
{
var dirPath = PathEx.Combine(
PathEx.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Directory.GetCurrentDirectory(),
"Temp"
);
Directory.CreateDirectory(dirPath);
var filePath = PathEx.Combine(
dirPath,
Guid.NewGuid() + ".tmp"
);
return new TempFile(filePath);
}
}

View file

@ -1,6 +1,5 @@
{ {
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"methodDisplayOptions": "all", "methodDisplayOptions": "all",
"methodDisplay": "method", "methodDisplay": "method"
"parallelizeTestCollections": true
} }

View file

@ -50,7 +50,7 @@ public class ChannelExporter
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
// Skips any messages that fail to pass the supplied filter // Skip messages that fail to pass the supplied filter
if (!request.MessageFilter.IsMatch(message)) if (!request.MessageFilter.IsMatch(message))
continue; continue;

View file

@ -78,13 +78,11 @@ internal partial class ExportAssetDownloader
internal partial class ExportAssetDownloader internal partial class ExportAssetDownloader
{ {
private static string GetUrlHash(string url) private static string GetUrlHash(string url) => SHA256
{ .HashData(Encoding.UTF8.GetBytes(url))
using var hash = SHA256.Create(); .ToHex()
// 5 chars ought to be enough for anybody
var data = hash.ComputeHash(Encoding.UTF8.GetBytes(url)); .Truncate(5);
return data.ToHex().Truncate(5); // 5 chars ought to be enough for anybody
}
private static string GetFileNameFromUrl(string url) private static string GetFileNameFromUrl(string url)
{ {

View file

@ -26,7 +26,7 @@ internal partial class MessageExporter : IAsyncDisposable
{ {
await _writer.WritePostambleAsync(cancellationToken); await _writer.WritePostambleAsync(cancellationToken);
} }
// Writer must be disposed, even if writing postamble fails // Writer must be disposed, even if it fails to write the postamble
finally finally
{ {
await _writer.DisposeAsync(); await _writer.DisposeAsync();
@ -45,16 +45,13 @@ internal partial class MessageExporter : IAsyncDisposable
_partitionIndex++; _partitionIndex++;
} }
// Writer is still valid - return // Writer is still valid, return
if (_writer is not null) if (_writer is not null)
return _writer; return _writer;
Directory.CreateDirectory(_context.Request.OutputBaseDirPath);
var filePath = GetPartitionFilePath(_context.Request.OutputBaseFilePath, _partitionIndex); var filePath = GetPartitionFilePath(_context.Request.OutputBaseFilePath, _partitionIndex);
var dirPath = Path.GetDirectoryName(_context.Request.OutputBaseFilePath);
if (!string.IsNullOrWhiteSpace(dirPath))
Directory.CreateDirectory(dirPath);
var writer = CreateMessageWriter(filePath, _context.Request.Format, _context); var writer = CreateMessageWriter(filePath, _context.Request.Format, _context);
await writer.WritePreambleAsync(cancellationToken); await writer.WritePreambleAsync(cancellationToken);
@ -74,7 +71,7 @@ internal partial class MessageExporter
{ {
private static string GetPartitionFilePath(string baseFilePath, int partitionIndex) private static string GetPartitionFilePath(string baseFilePath, int partitionIndex)
{ {
// First partition - don't change file name // First partition, don't change file name
if (partitionIndex <= 0) if (partitionIndex <= 0)
return baseFilePath; return baseFilePath;
@ -92,19 +89,14 @@ internal partial class MessageExporter
private static MessageWriter CreateMessageWriter( private static MessageWriter CreateMessageWriter(
string filePath, string filePath,
ExportFormat format, ExportFormat format,
ExportContext context) ExportContext context) =>
format switch
{ {
// Stream will be disposed by the underlying writer ExportFormat.PlainText => new PlainTextMessageWriter(File.Create(filePath), context),
var stream = File.Create(filePath); ExportFormat.Csv => new CsvMessageWriter(File.Create(filePath), context),
ExportFormat.HtmlDark => new HtmlMessageWriter(File.Create(filePath), context, "Dark"),
return format switch ExportFormat.HtmlLight => new HtmlMessageWriter(File.Create(filePath), context, "Light"),
{ ExportFormat.Json => new JsonMessageWriter(File.Create(filePath), context),
ExportFormat.PlainText => new PlainTextMessageWriter(stream, context),
ExportFormat.Csv => new CsvMessageWriter(stream, context),
ExportFormat.HtmlDark => new HtmlMessageWriter(stream, context, "Dark"),
ExportFormat.HtmlLight => new HtmlMessageWriter(stream, context, "Light"),
ExportFormat.Json => new JsonMessageWriter(stream, context),
_ => throw new ArgumentOutOfRangeException(nameof(format), $"Unknown export format '{format}'.") _ => throw new ArgumentOutOfRangeException(nameof(format), $"Unknown export format '{format}'.")
}; };
}
} }

View file

@ -6,12 +6,10 @@ public static class BinaryExtensions
{ {
public static string ToHex(this byte[] data) public static string ToHex(this byte[] data)
{ {
var buffer = new StringBuilder(); var buffer = new StringBuilder(2 * data.Length);
foreach (var t in data) foreach (var t in data)
{
buffer.Append(t.ToString("X2")); buffer.Append(t.ToString("X2"));
}
return buffer.ToString(); return buffer.ToString();
} }