import pytest
from visualizers.report_generator import ReportGenerator
class MockWorkoutData:
def __init__(self, summary_dict):
self.metadata = summary_dict.get("metadata", {})
self.summary = summary_dict.get("summary", {})
@pytest.fixture
def report_generator():
return ReportGenerator()
def _get_full_summary(date="2024-01-01"):
return {
"metadata": {
"start_time": f"{date} 10:00:00",
"sport": "Cycling",
"sub_sport": "Road",
"total_duration": 3600,
"total_distance_km": 30.0,
"avg_speed_kmh": 30.0,
"avg_hr": 150,
},
"summary": {"np": 220, "if": 0.85, "tss": 60},
}
def _get_partial_summary(date="2024-01-02"):
"""Summary missing NP, IF, and TSS."""
return {
"metadata": {
"start_time": f"{date} 09:00:00",
"sport": "Cycling",
"sub_sport": "Indoor",
"total_duration": 1800,
"total_distance_km": 15.0,
"avg_speed_kmh": 30.0,
"avg_hr": 145,
},
"summary": {}, # Missing optional keys
}
def test_summary_report_generation_with_full_data(report_generator, tmp_path):
workouts = [MockWorkoutData(_get_full_summary())]
analyses = [_get_full_summary()]
output_file = tmp_path / "summary.html"
html_output = report_generator.generate_summary_report(
workouts, analyses, format="html"
)
output_file.write_text(html_output)
assert output_file.exists()
content = output_file.read_text()
assert "
Workout Summary
" in content
assert "Date | " in content
assert "Sport | " in content
assert "Duration | " in content
assert "Distance (km) | " in content
assert "Avg Speed (km/h) | " in content
assert "Avg HR | " in content
assert "NP | " in content
assert "IF | " in content
assert "TSS | " in content
assert "2024-01-01 10:00:00 | " in content
assert "Cycling (Road) | " in content
assert "01:00:00 | " in content
assert "30.0 | " in content
assert "150 | " in content
assert "220 | " in content
assert "0.85 | " in content
assert "60 | " in content
def test_summary_report_gracefully_handles_missing_data(report_generator, tmp_path):
workouts = [
MockWorkoutData(_get_full_summary()),
MockWorkoutData(_get_partial_summary()),
]
analyses = [_get_full_summary(), _get_partial_summary()]
output_file = tmp_path / "summary_mixed.html"
html_output = report_generator.generate_summary_report(
workouts, analyses, format="html"
)
output_file.write_text(html_output)
assert output_file.exists()
content = output_file.read_text()
# Check that the table structure is there
assert content.count("") == 3 # Header + 2 data rows
# Check full data row
assert "| 220 | " in content
assert "0.85 | " in content
assert "60 | " in content
# Check partial data row - should have empty cells for missing data
assert "2024-01-02 09:00:00 | " in content
assert "Cycling (Indoor) | " in content
# Locate the row for the partial summary to check for empty cells
# A bit brittle, but good enough for this test
rows = content.split("
")
partial_row = [r for r in rows if "2024-01-02" in r][0]
cells = partial_row.split("| ")
# NP, IF, TSS are the last 3 cells. They should be empty or just contain whitespace.
assert " | " * 3 in partial_row.replace(" ", "").replace("\n", "")
assert " | " * 3 in partial_row.replace(" ", "").replace("\n", "")