"""Tests Sprint 67 — vue HTML d'un benchmark de pipeline composée.
Couvre :
1. ``build_pipeline_summary_html`` : affiche pipeline, corpus,
n_docs, succeeded/failed, durée totale.
2. ``build_pipeline_steps_table_html`` : tableau par étape avec
colonnes attendues, métriques aux jonctions formatées,
error_breakdown affiché, vide si aucune étape.
3. ``build_pipeline_report_html`` : document HTML autonome
(````, head, body, styles inline).
4. Anti-injection HTML : noms de pipeline / corpus / step
contenant ``",
corpus_name="demo",
)
html = build_pipeline_summary_html(bench)
assert "" not in html
assert "<script>" in html
def test_corpus_name_escaped(self) -> None:
bench = PipelineBenchmarkResult(
pipeline_name="p",
corpus_name="
",
)
html = build_pipeline_report_html(bench)
assert "
None:
bench = PipelineBenchmarkResult(
pipeline_name="p", corpus_name="c",
)
bench.per_step_aggregates = [
StepAggregate(
step_name="