# -*- coding: utf-8 -*- from backend.agents.skills_manager import SkillsManager from backend.skills.builtin.valuation_review.scripts.dcf_report import ( build_dcf_report, ) from backend.skills.builtin.valuation_review.scripts.multiple_valuation_report import ( build_ev_ebitda_report, build_residual_income_report, ) from backend.skills.builtin.valuation_review.scripts.owner_earnings_report import ( build_owner_earnings_report, ) def test_build_dcf_report_renders_assessment(): report = build_dcf_report( [ { "ticker": "AAPL", "current_fcf": 100.0, "growth_rate": 0.05, "market_cap": 900.0, "discount_rate": 0.10, "terminal_growth": 0.03, "num_years": 5, }, ], "2026-03-17", ) assert "DCF Valuation Analysis (2026-03-17)" in report assert "AAPL:" in report assert "Market Cap: $900" in report assert "Value Gap:" in report def test_build_owner_earnings_report_handles_errors(): report = build_owner_earnings_report( [ { "ticker": "MSFT", "error": "Negative owner earnings ($-50)", }, ], "2026-03-17", ) assert "MSFT: Negative owner earnings ($-50)" in report def test_multiple_valuation_reports_render_expected_sections(): ev_report = build_ev_ebitda_report( [ { "ticker": "NVDA", "current_multiple": 18.0, "median_multiple": 20.0, "current_ebitda": 50.0, "market_cap": 800.0, "net_debt": 100.0, }, ], "2026-03-17", ) residual_report = build_residual_income_report( [ { "ticker": "META", "book_value": 200.0, "initial_ri": 30.0, "market_cap": 300.0, "cost_of_equity": 0.10, "bv_growth": 0.03, "terminal_growth": 0.03, "num_years": 5, "margin_of_safety": 0.20, }, ], "2026-03-17", ) assert "EV/EBITDA Valuation (2026-03-17)" in ev_report assert "NVDA:" in ev_report assert "Residual Income Valuation (2026-03-17)" in residual_report assert "META:" in residual_report def test_prepare_active_skills_copies_skill_scripts(tmp_path): builtin_skill = tmp_path / "backend" / "skills" / "builtin" / "valuation_review" scripts_dir = builtin_skill / "scripts" scripts_dir.mkdir(parents=True, exist_ok=True) (builtin_skill / "SKILL.md").write_text( "---\nname: 估值分析\ndescription: desc\nversion: 1.0.0\n---\n", encoding="utf-8", ) (scripts_dir / "dcf_report.py").write_text("print('ok')\n", encoding="utf-8") manager = SkillsManager(project_root=tmp_path) active_map = manager.prepare_active_skills( config_name="demo", agent_defaults={"valuation_analyst": ["valuation_review"]}, ) active_dir = active_map["valuation_analyst"][0] assert (active_dir / "scripts" / "dcf_report.py").exists()