Implement HTML renderer with Jinja2

This commit is contained in:
2026-01-29 17:58:02 +00:00
parent 01d8295512
commit 5405ceec7f
2 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
"""Report renderers for HTML and PDF output."""
from py_dvt_ate.reporting.renderers.html import HTMLRenderer
__all__ = ["HTMLRenderer"]

View File

@@ -0,0 +1,100 @@
"""HTML renderer using Jinja2 templates.
This module provides HTML rendering for test reports using Jinja2 templating.
Templates are loaded from the package's templates directory.
"""
import base64
import json
from datetime import datetime
from importlib import resources
from pathlib import Path
from jinja2 import Environment, PackageLoader, select_autoescape
from py_dvt_ate import __version__
from py_dvt_ate.reporting.exceptions import TemplateRenderError
from py_dvt_ate.reporting.models import ReportData
class HTMLRenderer:
"""Renders HTML reports from ReportData using Jinja2 templates.
The renderer loads templates from the py_dvt_ate.reporting.templates package
and provides methods for rendering complete HTML reports.
"""
def __init__(self) -> None:
"""Initialise the HTML renderer with Jinja2 environment."""
self._env = Environment(
loader=PackageLoader("py_dvt_ate.reporting", "templates"),
autoescape=select_autoescape(["html", "xml"]),
)
self._css_content: str | None = None
def _load_css(self) -> str:
"""Load CSS content from the templates directory."""
if self._css_content is None:
templates_pkg = resources.files("py_dvt_ate.reporting.templates")
css_file = templates_pkg.joinpath("styles.css")
self._css_content = css_file.read_text()
return self._css_content
def _load_logo(self, logo_path: Path | None) -> str | None:
"""Load and encode logo image as base64.
Args:
logo_path: Path to logo image file.
Returns:
Base64-encoded image data, or None if no logo or file not found.
"""
if logo_path is None or not logo_path.exists():
return None
try:
with logo_path.open("rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
except OSError:
return None
def render(self, data: ReportData) -> str:
"""Render a test report to HTML.
Args:
data: Report data containing test run, results, and charts.
Returns:
Complete HTML document as a string.
Raises:
TemplateRenderError: If template rendering fails.
"""
try:
template = self._env.get_template("test_report.html")
# Format config JSON for display
config_formatted = ""
if data.run.config_json:
try:
config_dict = json.loads(data.run.config_json)
config_formatted = json.dumps(config_dict, indent=2)
except json.JSONDecodeError:
config_formatted = data.run.config_json
# Prepare template context
context = {
"data": data,
"css_content": self._load_css(),
"logo_base64": self._load_logo(data.config.logo_path),
"company_name": data.config.company_name,
"version": __version__,
"generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"config_formatted": config_formatted,
}
return template.render(**context)
except Exception as e:
msg = f"Failed to render HTML template: {e}"
raise TemplateRenderError(msg) from e