test(reports): add ReportEngine unit tests [FASE-2.1]

Stub WeasyPrint for CI-friendly PDF generation and verify HTML render, PDF path, and HTML file output.
This commit is contained in:
2026-05-18 14:00:37 +02:00
parent 0d4c404f08
commit c28a47c43b
2 changed files with 67 additions and 0 deletions

View File

@@ -76,6 +76,10 @@ class ReportEngine:
logger.info("DOCX generated: %s", output_path) logger.info("DOCX generated: %s", output_path)
return output_path return output_path
def generate_html(self, template_name: str, context: dict) -> str:
"""Render and save a standalone HTML report (alias for spec compatibility)."""
return self.generate_html_file(template_name, context)
def generate_html_file(self, template_name: str, context: dict) -> str: def generate_html_file(self, template_name: str, context: dict) -> str:
"""Render and save a standalone HTML report.""" """Render and save a standalone HTML report."""
html_content = self.render_html(template_name, context) html_content = self.render_html(template_name, context)

View File

@@ -0,0 +1,63 @@
"""Report engine unit tests (FASE-2.1)."""
import os
import sys
from unittest.mock import MagicMock
import pytest
from app.services.report_engine import ReportEngine
@pytest.fixture
def engine(tmp_path, monkeypatch):
templates = tmp_path / "templates"
styles = templates / "styles"
styles.mkdir(parents=True)
(styles / "report.css").write_text("body { color: #0e7490; }", encoding="utf-8")
(templates / "coverage_report.html").write_text(
"<html><body><h1>{{ company_name }}</h1><p>{{ score }}</p></body></html>",
encoding="utf-8",
)
out_dir = tmp_path / "out"
monkeypatch.setattr("app.services.report_engine.settings.REPORT_TEMPLATES_DIR", str(templates))
monkeypatch.setattr("app.services.report_engine.settings.REPORT_OUTPUT_DIR", str(out_dir))
monkeypatch.setattr("app.services.report_engine.settings.COMPANY_NAME", "Test Org")
return ReportEngine()
def test_render_html_injects_company_and_timestamp(engine):
html = engine.render_html("coverage_report", {"score": 42})
assert "Test Org" in html
assert "42" in html
def test_generate_pdf_writes_file(engine, monkeypatch, tmp_path):
"""WeasyPrint is stubbed so tests run without GTK/Pango system libraries."""
def _write_pdf(output_path, stylesheets=None):
with open(output_path, "wb") as f:
f.write(b"%PDF-1.4 mock")
mock_html_instance = MagicMock()
mock_html_instance.write_pdf.side_effect = _write_pdf
mock_wp = MagicMock()
mock_wp.HTML.return_value = mock_html_instance
mock_wp.CSS = MagicMock()
for key in list(sys.modules):
if key == "weasyprint" or key.startswith("weasyprint."):
monkeypatch.delitem(sys.modules, key, raising=False)
monkeypatch.setitem(sys.modules, "weasyprint", mock_wp)
path = engine.generate_pdf("coverage_report", {"score": 99})
assert path.endswith(".pdf")
assert os.path.isfile(path)
mock_html_instance.write_pdf.assert_called_once()
def test_generate_html_file_writes_file(engine):
path = engine.generate_html("coverage_report", {"score": 7})
assert path.endswith(".html")
assert os.path.isfile(path)
with open(path, encoding="utf-8") as f:
assert "Test Org" in f.read()