"""Sprint A14-S21 — ``ReportService`` (rendu HTML depuis ``RunResult``).
Couverture :
- Rendu basique : header (corpus, run_id, code_version, timestamps),
vue d'ensemble pipelines (succès/échecs/durée), une section par
vue avec table pipeline × métriques.
- **Pattern d'omission visible** : un pipeline qui ne produit pas
d'artefact éligible affiche ``OMIS`` (pas un ``0`` factice).
- Anti-injection : ``corpus_name`` / ``view.name`` /
``pipeline_name`` contenant ``",
views=(view,),
)
result = RunResult(manifest=manifest, document_results=())
html = ReportService().render(result)
assert "" not in html
assert "<script>alert(1)</script>" in html
def test_pipeline_name_with_html_is_escaped(self) -> None:
view = _empty_view()
manifest = _manifest(
pipeline_names=("
",),
views=(view,),
)
result = RunResult(manifest=manifest, document_results=())
html = ReportService().render(result)
assert "
None:
view = _empty_view(
name="evil_name",
description='',
)
manifest = _manifest(views=(view,))
result = RunResult(manifest=manifest, document_results=())
html = ReportService().render(result)
assert "