223 lines
7.3 KiB
Python
223 lines
7.3 KiB
Python
"""Unit tests for HTML renderer."""
|
|
|
|
from datetime import datetime
|
|
|
|
import pytest
|
|
|
|
from py_dvt_ate.data.models import TestResult, TestRun, TestStatus
|
|
from py_dvt_ate.reporting.exceptions import TemplateRenderError
|
|
from py_dvt_ate.reporting.models import ReportConfig, ReportData
|
|
from py_dvt_ate.reporting.renderers.html import HTMLRenderer
|
|
|
|
|
|
class TestHTMLRenderer:
|
|
"""Tests for HTMLRenderer class."""
|
|
|
|
@pytest.fixture
|
|
def renderer(self) -> HTMLRenderer:
|
|
"""Create an HTML renderer instance."""
|
|
return HTMLRenderer()
|
|
|
|
@pytest.fixture
|
|
def sample_run(self) -> TestRun:
|
|
"""Create a sample test run."""
|
|
return TestRun(
|
|
id="12345678-1234-1234-1234-123456789abc",
|
|
test_name="tempco",
|
|
started_at=datetime(2024, 1, 15, 10, 30, 0),
|
|
completed_at=datetime(2024, 1, 15, 10, 35, 0),
|
|
status=TestStatus.PASSED,
|
|
config_json='{"temperatures": [-40, 25, 85], "input_voltage": 5.0}',
|
|
operator="test_user",
|
|
description="Temperature coefficient characterisation test",
|
|
)
|
|
|
|
@pytest.fixture
|
|
def sample_results(self) -> list[TestResult]:
|
|
"""Create sample test results."""
|
|
return [
|
|
TestResult(
|
|
id="result-1",
|
|
test_run_id="12345678-1234-1234-1234-123456789abc",
|
|
parameter="tempco",
|
|
value=45.0,
|
|
unit="ppm/C",
|
|
measured_at=datetime(2024, 1, 15, 10, 35, 0),
|
|
lower_limit=None,
|
|
upper_limit=100.0,
|
|
),
|
|
TestResult(
|
|
id="result-2",
|
|
test_run_id="12345678-1234-1234-1234-123456789abc",
|
|
parameter="output_voltage_25c",
|
|
value=3.3001,
|
|
unit="V",
|
|
measured_at=datetime(2024, 1, 15, 10, 33, 0),
|
|
lower_limit=3.2,
|
|
upper_limit=3.4,
|
|
),
|
|
]
|
|
|
|
@pytest.fixture
|
|
def sample_report_data(
|
|
self, sample_run: TestRun, sample_results: list[TestResult]
|
|
) -> ReportData:
|
|
"""Create sample report data."""
|
|
return ReportData(
|
|
run=sample_run,
|
|
results=sample_results,
|
|
config=ReportConfig(company_name="Test Company"),
|
|
)
|
|
|
|
def test_render_produces_html(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render produces valid HTML output."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
assert isinstance(html, str)
|
|
assert html.startswith("<!DOCTYPE html>")
|
|
assert "</html>" in html
|
|
|
|
def test_render_includes_title(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes the test name in title."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
assert "<title>" in html
|
|
assert "tempco" in html
|
|
|
|
def test_render_includes_company_name(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes the company name."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
assert "Test Company" in html
|
|
|
|
def test_render_includes_results_table(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes results in a table."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
# Check for parameter names in output
|
|
assert "tempco" in html
|
|
assert "output_voltage_25c" in html
|
|
|
|
# Check for values
|
|
assert "45.000000" in html
|
|
assert "3.300100" in html
|
|
|
|
def test_render_includes_pass_status(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render shows pass status badges."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
# Check for PASS badge (results should pass)
|
|
assert "PASS" in html
|
|
|
|
def test_render_includes_run_metadata(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes run metadata."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
assert "12345678-1234-1234-1234-123456789abc" in html
|
|
assert "test_user" in html
|
|
assert "Temperature coefficient characterisation test" in html
|
|
|
|
def test_render_includes_css(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes CSS styles."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
# Check for some CSS from styles.css
|
|
assert "<style>" in html
|
|
assert "@page" in html or "font-family" in html
|
|
|
|
def test_render_includes_configuration(
|
|
self, renderer: HTMLRenderer, sample_report_data: ReportData
|
|
) -> None:
|
|
"""Test that render includes test configuration."""
|
|
html = renderer.render(sample_report_data)
|
|
|
|
# Check for config values (formatted JSON)
|
|
assert "temperatures" in html
|
|
assert "input_voltage" in html
|
|
|
|
def test_render_with_charts(
|
|
self, renderer: HTMLRenderer, sample_run: TestRun, sample_results: list[TestResult]
|
|
) -> None:
|
|
"""Test that render includes chart images."""
|
|
# Create sample base64 chart data
|
|
charts = {
|
|
"Test Chart": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
|
|
}
|
|
|
|
data = ReportData(
|
|
run=sample_run,
|
|
results=sample_results,
|
|
charts=charts,
|
|
config=ReportConfig(),
|
|
)
|
|
|
|
html = renderer.render(data)
|
|
|
|
# Check for chart section and base64 image
|
|
assert "Charts" in html
|
|
assert "data:image/png;base64," in html
|
|
|
|
def test_render_empty_results(
|
|
self, renderer: HTMLRenderer, sample_run: TestRun
|
|
) -> None:
|
|
"""Test rendering with no results."""
|
|
data = ReportData(
|
|
run=sample_run,
|
|
results=[],
|
|
config=ReportConfig(),
|
|
)
|
|
|
|
html = renderer.render(data)
|
|
|
|
# Should still produce valid HTML
|
|
assert "<!DOCTYPE html>" in html
|
|
assert "No results recorded" in html
|
|
|
|
def test_css_is_cached(self, renderer: HTMLRenderer) -> None:
|
|
"""Test that CSS content is cached after first load."""
|
|
# Access CSS twice
|
|
css1 = renderer._load_css()
|
|
css2 = renderer._load_css()
|
|
|
|
# Should be the same object (cached)
|
|
assert css1 is css2
|
|
assert len(css1) > 0
|
|
|
|
def test_render_formats_limits(
|
|
self, renderer: HTMLRenderer, sample_run: TestRun
|
|
) -> None:
|
|
"""Test that limits are properly formatted."""
|
|
results = [
|
|
TestResult(
|
|
id="result-1",
|
|
test_run_id="12345678-1234-1234-1234-123456789abc",
|
|
parameter="test_param",
|
|
value=50.0,
|
|
unit="units",
|
|
measured_at=datetime(2024, 1, 15, 10, 35, 0),
|
|
lower_limit=10.0,
|
|
upper_limit=100.0,
|
|
),
|
|
]
|
|
|
|
data = ReportData(run=sample_run, results=results, config=ReportConfig())
|
|
html = renderer.render(data)
|
|
|
|
# Check limits are formatted
|
|
assert "10.000000" in html
|
|
assert "100.000000" in html
|