import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parent.parent TOOLS_DIR = PROJECT_ROOT / "tools" if str(TOOLS_DIR) not in sys.path: sys.path.insert(0, str(TOOLS_DIR)) from oci_bizcase_gen import BusinessCaseDeckGenerator def _collect_slide_text(gen): texts = [] for slide in gen.prs.slides: for shape in slide.shapes: if hasattr(shape, "text"): text = shape.text.strip() if text: texts.append(text) if getattr(shape, "has_table", False): for row in shape.table.rows: for cell in row.cells: text = cell.text.strip() if text: texts.append(text) return "\n".join(texts) def test_from_spec_accepts_cover_aliases_and_recommendation_fallback(): spec = { "customer": "Acme Corp", "author": "Diego", "generated_on": "2026-04-21", "recommendation": { "commitment_amount": "100K", "commitment_type": "UCM", }, } gen = BusinessCaseDeckGenerator.from_spec(spec) text = _collect_slide_text(gen) assert "Acme Corp" in text assert "Prepared by: Diego" in text assert "Recommended: 100K UCM commitment" in text def test_from_spec_accepts_roadmap_aliases_and_mixed_next_steps(): spec = { "customer_name": "Acme Corp", "roadmap": { "phases": [ { "title": "Assess", "weeks": "2 weeks", "outputs": ["Blueprint"], "milestones": ["Kickoff"], } ], "total_duration": "6 weeks", }, "recommendation": { "summary": "Proceed with phased migration", "next_steps": [ "Confirm scope", {"action": "Approve budget", "owner": "Finance", "deadline": "May"}, ], }, } gen = BusinessCaseDeckGenerator.from_spec(spec) text = _collect_slide_text(gen) assert "Assess" in text assert "2 weeks" in text assert "Kickoff" in text assert "Blueprint" in text assert "Confirm scope" in text assert "Approve budget" in text assert "Finance" in text assert "May" in text