using System; using System.IO; using System.Threading.Tasks; using DiscordChatExporter.Core.Discord; using DiscordChatExporter.Core.Discord.Data; using DiscordChatExporter.Core.Exporting; using DiscordChatExporter.Core.Exporting.Filtering; using DiscordChatExporter.Core.Exporting.Partitioning; using FluentAssertions; using Xunit; namespace DiscordChatExporter.Cli.Tests.Specs; public class HtmlMarkdownHeadingSpecs { private static async ValueTask FormatMarkdownAsync(string markdown) => await HtmlMarkdownVisitor.FormatAsync(null!, markdown); private static ExportContext CreateExportContext(bool shouldFormatMarkdown) { var guild = Guild.DirectMessages; var channel = new Channel( new Snowflake(1), ChannelKind.DirectTextChat, guild.Id, null, "test", null, null, null, false, null ); var request = new ExportRequest( guild, channel, Path.Combine(Path.GetTempPath(), "DiscordChatExporter.Tests", "test.html"), null, ExportFormat.HtmlDark, null, null, PartitionLimit.Null, MessageFilter.Null, false, shouldFormatMarkdown, false, true, "en-US", true ); return new ExportContext(new DiscordClient(""), request); } private static Message CreateMessage(string content) => new( new Snowflake(2), MessageKind.Default, MessageFlags.None, new User(new Snowflake(3), false, 1234, "test-user", "Test User", ""), DateTimeOffset.Parse("2024-01-01T00:00:00+00:00"), null, null, false, content, [], [], [], [], [], null, null, null, null ); [Theory] [InlineData("# Heading", "

Heading

")] [InlineData("# Heading\nbody", "

Heading

body")] [InlineData("# Heading\r\nbody", "

Heading

body")] [InlineData("## Heading", "

Heading

")] [InlineData("### Heading", "

Heading

")] public async Task I_can_render_markdown_headings_as_html(string markdown, string expectedHtml) { // Act var html = await FormatMarkdownAsync(markdown); // Assert html.Should().Be(expectedHtml); } [Theory] [InlineData("#hashtag")] [InlineData("#")] [InlineData("#\nHeading")] [InlineData("#\r\nHeading")] public async Task I_do_not_render_non_heading_hash_text_as_html_heading(string markdown) { // Act var html = await FormatMarkdownAsync(markdown); // Assert html.Should().Be(markdown); html.Should().NotContain(" & \"quote\""); // Assert html.Should().Be("

<Heading> & "quote"

"); } [Fact] public async Task I_keep_markdown_headings_literal_when_formatting_is_disabled() { // Arrange var context = CreateExportContext(false); var message = CreateMessage("# & \"quote\""); // Act var html = await new MessageGroupTemplate { Context = context, Messages = [message], }.RenderAsync(); // Assert html.Should().Contain("# <Heading> &"); html.Should().NotContain("# "); html.Should().NotContain("

"); } }