"""Tests for core.export.report_data — envelope shape and computed totals.""" from __future__ import annotations from unittest.mock import MagicMock import pytest from core.export import build_report_data from core.export.report_data import _compute_summary, _yearly_totals class TestComputeSummary: def test_amazon_connect_totals(self, amazon_connect_seed): s = _compute_summary( amazon_connect_seed.BENEFITS, amazon_connect_seed.COSTS, 0.10, 3, ) assert s["total_benefits_pv"] == pytest.approx(101_696_791, abs=1500) assert s["total_costs_pv"] == pytest.approx(22_983_076, abs=1500) assert s["npv"] == pytest.approx(78_713_715, abs=2000) assert s["roi_pct"] == pytest.approx(342, abs=1) assert s["payback_months"] is not None and s["payback_months"] < 6 def test_yearly_breakdown_three_rows(self, amazon_connect_seed): s = _compute_summary( amazon_connect_seed.BENEFITS, amazon_connect_seed.COSTS, 0.10, 3 ) assert len(s["yearly_breakdown"]) == 3 assert [r["year"] for r in s["yearly_breakdown"]] == [1, 2, 3] class TestYearlyTotals: def test_only_within_horizon(self): items = [ {"year_values": {"1": 100, "2": 200, "3": 300, "4": 999}}, ] assert _yearly_totals(items, 3) == [100.0, 200.0, 300.0] def test_skips_invalid_keys(self): items = [{"year_values": {"1": 50, "abc": 999}}] assert _yearly_totals(items, 2) == [50.0, 0.0] class TestBuildReportData: def _stub_client(self, seed): c = MagicMock() c.get_tool_with_data.return_value = { "tool": {"id": "pid", "name": "T", "report": "rid", "proposal": 7}, "fields": [], "values": seed.BENEFITS + seed.COSTS, } c.get_report.return_value = { "id": "rid", "name": "Amazon Connect", "vendor": "AWS", "version": "1.0", "discount_rate": "0.10", "analysis_period_years": 3, } c.export.return_value = {"echoed": True} return c def test_envelope_shape(self, amazon_connect_seed): client = self._stub_client(amazon_connect_seed) env = build_report_data(client, "pid", study_slug="202602_AmazonConnect") assert set(env) >= { "metadata", "report", "fields", "values", "summary", "athena_export", "scenarios", } assert env["metadata"]["study_slug"] == "202602_AmazonConnect" assert env["metadata"]["proposal"] == 7 assert env["values"]["benefits"] assert env["values"]["costs"] def test_scenarios_have_three_keys(self, amazon_connect_seed): client = self._stub_client(amazon_connect_seed) env = build_report_data(client, "pid") assert set(env["scenarios"]) == {"conservative", "moderate", "aggressive"} def test_no_scenarios_flag(self, amazon_connect_seed): client = self._stub_client(amazon_connect_seed) env = build_report_data(client, "pid", include_scenarios=False) assert "scenarios" not in env def test_local_summary_matches_seed(self, amazon_connect_seed): client = self._stub_client(amazon_connect_seed) env = build_report_data(client, "pid", include_scenarios=False) assert env["summary"]["total_benefits_pv"] == pytest.approx( 101_696_791, abs=1500 )