using Eis.Infrastructure.Public; namespace Eis.Infrastructure.Tests.Public; public sealed class NoticeContentFormatterTests { private readonly NoticeContentFormatter _formatter = new(); [Fact] public void Sanitize_RemovesExecutableMarkupAndUnsafeAttributes() { const string source = "

正文链接

"; var result = _formatter.Sanitize(source); Assert.Contains("正文", result, StringComparison.Ordinal); Assert.Contains("链接", result, StringComparison.Ordinal); Assert.DoesNotContain("script", result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("onclick", result, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("javascript:", result, StringComparison.OrdinalIgnoreCase); } [Fact] public void Sanitize_PreservesSupportedEditorMarkupAndHardensLinks() { const string source = "
\"图\"
说明
详情"; var result = _formatter.Sanitize(source); Assert.Contains("class=\"image\"", result, StringComparison.Ordinal); Assert.DoesNotContain("unknown", result, StringComparison.Ordinal); Assert.Contains("src=\"https://example.test/a.png\"", result, StringComparison.Ordinal); Assert.Contains("rel=\"noopener noreferrer\"", result, StringComparison.Ordinal); } [Fact] public void PlainText_PreservesBlockBoundariesAndDecodesEntities() { const string source = "

第一段 内容

"; var result = _formatter.PlainText(source); Assert.Equal("第一段 内容 第二项", result); } [Fact] public void ContentHtml_ConvertsPlainTextParagraphsWithoutTrustingMarkup() { const string source = "第一段\n换行\n\n第二段 & 内容"; var result = _formatter.ContentHtml(source); Assert.Equal("

第一段
换行

第二段 & 内容

", result); } }