108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
|
|
"""
|
||
|
|
Tests de l'extraction HTML depuis les fichiers .eml (pipeline._eml_to_html).
|
||
|
|
|
||
|
|
Stratégie : on construit des .eml synthétiques en mémoire (tmp_path)
|
||
|
|
sans dépendre d'un vrai mail Picnic.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from tickettracker.pipeline import _eml_to_html
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Helpers pour construire des .eml de test
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
def _make_eml(tmp_path: Path, html: str, add_text_part: bool = True) -> Path:
|
||
|
|
"""Crée un fichier .eml multipart/alternative avec une partie HTML."""
|
||
|
|
boundary = "BOUNDARY123"
|
||
|
|
lines = [
|
||
|
|
"MIME-Version: 1.0",
|
||
|
|
f'Content-Type: multipart/alternative; boundary="{boundary}"',
|
||
|
|
"From: picnic@picnic.app",
|
||
|
|
"Subject: Votre commande Picnic",
|
||
|
|
"",
|
||
|
|
f"--{boundary}",
|
||
|
|
]
|
||
|
|
if add_text_part:
|
||
|
|
lines += [
|
||
|
|
"Content-Type: text/plain; charset=utf-8",
|
||
|
|
"",
|
||
|
|
"Version texte de l'email.",
|
||
|
|
"",
|
||
|
|
f"--{boundary}",
|
||
|
|
]
|
||
|
|
lines += [
|
||
|
|
"Content-Type: text/html; charset=utf-8",
|
||
|
|
"",
|
||
|
|
html,
|
||
|
|
"",
|
||
|
|
f"--{boundary}--",
|
||
|
|
]
|
||
|
|
p = tmp_path / "ticket.eml"
|
||
|
|
p.write_text("\n".join(lines), encoding="utf-8")
|
||
|
|
return p
|
||
|
|
|
||
|
|
|
||
|
|
def _make_eml_no_html(tmp_path: Path) -> Path:
|
||
|
|
"""Crée un .eml sans partie HTML (texte seul)."""
|
||
|
|
boundary = "BOUNDARY456"
|
||
|
|
content = "\n".join([
|
||
|
|
"MIME-Version: 1.0",
|
||
|
|
f'Content-Type: multipart/alternative; boundary="{boundary}"',
|
||
|
|
"",
|
||
|
|
f"--{boundary}",
|
||
|
|
"Content-Type: text/plain; charset=utf-8",
|
||
|
|
"",
|
||
|
|
"Texte seul, pas de HTML.",
|
||
|
|
"",
|
||
|
|
f"--{boundary}--",
|
||
|
|
])
|
||
|
|
p = tmp_path / "no_html.eml"
|
||
|
|
p.write_text(content, encoding="utf-8")
|
||
|
|
return p
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Tests
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
def test_eml_to_html_retourne_le_contenu_html(tmp_path):
|
||
|
|
"""_eml_to_html extrait correctement le HTML d'un .eml multipart."""
|
||
|
|
html = "<html><body><p>Commande Picnic</p></body></html>"
|
||
|
|
eml = _make_eml(tmp_path, html)
|
||
|
|
result = _eml_to_html(eml)
|
||
|
|
assert "Commande Picnic" in result
|
||
|
|
|
||
|
|
|
||
|
|
def test_eml_to_html_contient_les_balises(tmp_path):
|
||
|
|
"""Le HTML retourné contient bien les balises HTML."""
|
||
|
|
html = "<html><body><h1>Titre</h1></body></html>"
|
||
|
|
eml = _make_eml(tmp_path, html)
|
||
|
|
result = _eml_to_html(eml)
|
||
|
|
assert "<h1>" in result or "Titre" in result
|
||
|
|
|
||
|
|
|
||
|
|
def test_eml_to_html_retourne_str(tmp_path):
|
||
|
|
"""_eml_to_html retourne une chaîne de caractères."""
|
||
|
|
eml = _make_eml(tmp_path, "<html><body>test</body></html>")
|
||
|
|
result = _eml_to_html(eml)
|
||
|
|
assert isinstance(result, str)
|
||
|
|
|
||
|
|
|
||
|
|
def test_eml_to_html_sans_partie_texte(tmp_path):
|
||
|
|
"""Fonctionne aussi sur un .eml avec uniquement une partie HTML."""
|
||
|
|
html = "<html><body><p>HTML only</p></body></html>"
|
||
|
|
eml = _make_eml(tmp_path, html, add_text_part=False)
|
||
|
|
result = _eml_to_html(eml)
|
||
|
|
assert "HTML only" in result
|
||
|
|
|
||
|
|
|
||
|
|
def test_eml_to_html_leve_valueerror_si_pas_de_html(tmp_path):
|
||
|
|
"""Lève ValueError si le .eml ne contient aucune partie HTML."""
|
||
|
|
eml = _make_eml_no_html(tmp_path)
|
||
|
|
with pytest.raises(ValueError, match="Aucune partie HTML"):
|
||
|
|
_eml_to_html(eml)
|