from pathlib import Path import pytest from fin_hub.services.evaluate import evaluate_runway from fin_hub.services.evidence import build_runway_report, seed_fixture_ledger, write_runway_evidence from fin_hub.services.ledger import import_csv, monthly_burn_series, monthly_summary, set_opening_balance FIXTURES = Path(__file__).parent / "fixtures" def test_ledger_import_and_monthly_summary(tmp_path: Path): ledger = tmp_path / "ledger.db" set_opening_balance(ledger, 12000.0) cloud = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger) host = import_csv(FIXTURES / "hosteurope.csv", "hosteurope", ledger_path=ledger) assert cloud.rows_imported == 3 assert host.rows_imported == 2 rollups = monthly_summary(ledger_path=ledger) eur_totals = {rollup.period_month: rollup.total for rollup in rollups if rollup.currency == "EUR"} assert eur_totals["2026-06"] == pytest.approx(85.5 + 99.8) burns = monthly_burn_series(ledger_path=ledger, currency="EUR") assert burns == [pytest.approx(185.3)] def test_ledger_import_skips_unchanged_file(tmp_path: Path): ledger = tmp_path / "ledger.db" first = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger) second = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger) assert first.rows_imported == 3 assert second.skipped is True assert second.rows_imported == 0 def test_evaluate_runway_from_ledger(tmp_path: Path): ledger = tmp_path / "ledger.db" seed_fixture_ledger(ledger_path=ledger, opening_balance=12000.0) report = evaluate_runway(ledger_path=ledger, alert_threshold_months=3.0) assert report["runway"]["current_balance"] == 12000.0 assert report["runway"]["monthly_burn"] > 0 def test_build_runway_report_and_write_evidence(tmp_path: Path): ledger = tmp_path / "ledger.db" seed_fixture_ledger(ledger_path=ledger, opening_balance=12000.0) text = build_runway_report(ledger_path=ledger) assert "Runway Dogfood Evidence" in text assert "2026-06" in text output = write_runway_evidence( ledger_path=ledger, output_dir=tmp_path / "evidence", opening_balance=12000.0, ) assert output.exists() assert "runway-dogfood-" in output.name