Files
Omika/tests/Omika.Tests/Mobile/Local/EmailHtmlParserTests.cs
T
2026-10-23 18:46:50 +02:00

129 lines
4.8 KiB
C#

using Omika.App.Controls;
namespace Omika.Tests.Mobile.Local;
/// <summary>
/// Tests du parseur HTML de l'aperçu Email (<see cref="EmailHtmlParser"/>) :
/// le sous-ensemble produit par DocxHtmlConverter (paragraphes, tableaux, images
/// data URI auto-fermantes, gras/italique) est transformé en modèle structuré,
/// sans jamais exposer de balises brutes.
/// </summary>
public class EmailHtmlParserTests
{
private static readonly byte[] Png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
private static string Img(string mime, byte[] bytes) =>
$"<img src=\"data:{mime};base64,{Convert.ToBase64String(bytes)}\" />";
private static IReadOnlyList<HtmlInline> InlinesPremierBloc(string html)
=> EmailHtmlParser.Parser(html)[0] switch
{
HtmlParagraph p => p.Inlines,
_ => throw new InvalidOperationException("Premier bloc non paragraphe.")
};
// TEST 1 : paragraphe → texte visible
[Fact]
public void Paragraphe_TexteVisible()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc("<p>Bonjour</p>");
HtmlRun run = Assert.IsType<HtmlRun>(Assert.Single(inlines));
Assert.Equal("Bonjour", run.Text);
}
// TEST 2 : table → 1 ligne / 2 cellules
[Fact]
public void Tableau_UneLigne_DeuxCellules()
{
HtmlBlock bloc = Assert.Single(EmailHtmlParser.Parser("<table><tr><td>A</td><td>B</td></tr></table>"));
HtmlTable table = Assert.IsType<HtmlTable>(bloc);
HtmlRow row = Assert.Single(table.Rows);
Assert.Equal(2, row.Cells.Count);
Assert.Equal("A", Assert.IsType<HtmlRun>(Assert.Single(row.Cells[0].Inlines)).Text);
Assert.Equal("B", Assert.IsType<HtmlRun>(Assert.Single(row.Cells[1].Inlines)).Text);
}
// TEST 3 : img PNG data URI → image créée
[Fact]
public void Image_PngDataUri_Decodee()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc($"<p>{Img("image/png", Png)}</p>");
HtmlImage image = Assert.IsType<HtmlImage>(Assert.Single(inlines));
Assert.Equal("image/png", image.MimeType);
Assert.Equal(Convert.ToBase64String(Png), image.Base64Data);
}
// TEST 4 : 2 img → 2 images
[Fact]
public void DeuxImages_DeuxImages()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc(
$"<p>{Img("image/png", Png)}{Img("image/jpeg", [0xFF, 0xD8, 0xFF, 0xE0])}</p>");
Assert.Equal(2, inlines.OfType<HtmlImage>().Count());
}
// TEST 5 : Base64 invalide → pas de crash, pas d'image
[Fact]
public void Image_Base64Invalide_SansCrash()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc(
"<p><img src=\"data:image/png;base64,!!!pas-du-base64!!!\" /></p>");
Assert.DoesNotContain(inlines, i => i is HtmlImage);
}
// TEST 6 : texte + image + texte → ordre conservé
[Fact]
public void Texte_Image_Texte_OrdreConserve()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc(
$"<p>Avant{Img("image/png", Png)}Après</p>");
Assert.Equal(3, inlines.Count);
Assert.Equal("Avant", Assert.IsType<HtmlRun>(inlines[0]).Text);
Assert.IsType<HtmlImage>(inlines[1]);
Assert.Equal("Après", Assert.IsType<HtmlRun>(inlines[2]).Text);
}
// TEST 7 : image dans une cellule de tableau → bonne cellule
[Fact]
public void Image_DansCelluleTableau()
{
HtmlTable table = Assert.IsType<HtmlTable>(Assert.Single(EmailHtmlParser.Parser(
$"<table><tr><td>{Img("image/png", Png)}</td><td>30/01/2026</td></tr></table>")));
Assert.Single(table.Rows);
Assert.Contains(table.Rows[0].Cells[0].Inlines, i => i is HtmlImage);
Assert.Equal("30/01/2026", Assert.IsType<HtmlRun>(Assert.Single(table.Rows[0].Cells[1].Inlines)).Text);
}
// TEST 8 : aucune balise HTML brute affichée (entités décodées)
[Fact]
public void AucuneBaliseHtmlBrute_EntitesDecodees()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc("<p>Bonjour &amp; bienvenue &lt;test&gt;</p>");
HtmlRun run = Assert.IsType<HtmlRun>(Assert.Single(inlines));
Assert.Equal("Bonjour & bienvenue <test>", run.Text);
Assert.DoesNotContain("&amp;", run.Text);
Assert.DoesNotContain("<p>", run.Text);
}
// Gras / italique / souligné propagés
[Fact]
public void Formatage_GrasItalique_Souligne()
{
IReadOnlyList<HtmlInline> inlines = InlinesPremierBloc(
"<p><b>Gras</b> <i>Italique</i> <u>Souligné</u></p>");
Assert.Equal(5, inlines.Count);
Assert.True(Assert.IsType<HtmlRun>(inlines[0]).Bold);
Assert.True(Assert.IsType<HtmlRun>(inlines[2]).Italic);
Assert.True(Assert.IsType<HtmlRun>(inlines[4]).Underline);
}
}