""" Unit tests for compose() — the brain. Tests cover: message body generation, CTA, template params, category-specific outputs, and customer-facing messages. """ import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from app.core.compose import compose # ── Sample contexts for testing ───────────────────────────────────────────── DENTIST_CATEGORY = { "slug": "dentists", "voice": {"tone": "peer_clinical", "vocab_taboo": ["cure", "guaranteed"]}, "peer_stats": {"avg_rating": 4.4, "avg_ctr": 0.030}, "digest": [ {"id": "d_2026W17_jida_fluoride", "kind": "research", "title": "3-mo fluoride recall cuts caries recurrence 38% better than 6-mo", "source": "JIDA Oct 2026, p.14", "trial_n": 2100, "patient_segment": "high_risk_adults"} ], "offer_catalog": [], "seasonal_beats": [], "trend_signals": [], } MERCHANT_DRMEERA = { "merchant_id": "m_001_drmeera", "category_slug": "dentists", "identity": {"name": "Dr. Meera's Dental Clinic", "owner_first_name": "Meera", "city": "Delhi", "locality": "Lajpat Nagar", "verified": True, "languages": ["en", "hi"]}, "subscription": {"status": "active", "plan": "Pro", "days_remaining": 82}, "performance": {"views": 2410, "calls": 18, "directions": 45, "ctr": 0.021, "delta_7d": {"views_pct": 0.18, "calls_pct": -0.05}}, "offers": [{"id": "o1", "title": "Dental Cleaning @ ₹299", "status": "active"}], "customer_aggregate": {"total_unique_ytd": 540, "lapsed_180d_plus": 78, "retention_6mo_pct": 0.38, "high_risk_adult_count": 124}, "signals": ["stale_posts:22d", "ctr_below_peer_median"], "review_themes": [], } TRIGGER_RESEARCH = { "id": "trg_001", "scope": "merchant", "kind": "research_digest", "source": "external", "merchant_id": "m_001_drmeera", "payload": {"category": "dentists", "top_item_id": "d_2026W17_jida_fluoride"}, "urgency": 2, "suppression_key": "research:dentists:2026-W17", "expires_at": "2026-05-03T00:00:00Z", } TRIGGER_PERF_DIP = { "id": "trg_004", "scope": "merchant", "kind": "perf_dip", "source": "internal", "merchant_id": "m_002", "payload": {"metric": "calls", "delta_pct": -0.50, "window": "7d"}, "urgency": 4, "suppression_key": "perf_dip:m_002:calls:2026-W17", } CUSTOMER_PRIYA = { "customer_id": "c_001_priya", "merchant_id": "m_001_drmeera", "identity": {"name": "Priya", "language_pref": "hi-en mix"}, "relationship": {"visits_total": 4, "last_visit": "2026-05-12"}, "state": "lapsed_soft", } TRIGGER_RECALL = { "id": "trg_003", "scope": "customer", "kind": "recall_due", "source": "internal", "merchant_id": "m_001_drmeera", "customer_id": "c_001_priya", "payload": {"service_due": "6_month_cleaning", "available_slots": [{"label": "Wed 5 Nov, 6pm"}, {"label": "Thu 6 Nov, 5pm"}]}, "urgency": 3, "suppression_key": "recall:c_001:6mo", } # ── Tests ──────────────────────────────────────────────────────────────────── def test_research_digest_compose(): result = compose(DENTIST_CATEGORY, MERCHANT_DRMEERA, TRIGGER_RESEARCH) assert "body" in result assert len(result["body"]) > 30 # Should mention JIDA assert "JIDA" in result["body"] or "jida" in result["body"].lower() # Should mention the merchant's patients assert "124" in result["body"] or "high-risk" in result["body"] # Should have a CTA assert "?" in result["body"] print(f"PASS: research_digest — {result['body'][:80]}...") def test_perf_dip_compose(): merchant = {**MERCHANT_DRMEERA, "merchant_id": "m_002", "performance": {"views": 980, "calls": 4, "delta_7d": {"calls_pct": -0.50}}} result = compose(DENTIST_CATEGORY, merchant, TRIGGER_PERF_DIP) assert "body" in result assert "50%" in result["body"] or "calls" in result["body"] print(f"PASS: perf_dip — {result['body'][:80]}...") def test_recall_customer_facing(): result = compose(DENTIST_CATEGORY, MERCHANT_DRMEERA, TRIGGER_RECALL, CUSTOMER_PRIYA) assert "body" in result assert "Priya" in result["body"] assert "Dental Clinic" in result["body"] or "Dr. Meera" in result["body"] print(f"PASS: recall — {result['body'][:80]}...") def test_no_taboo_terms(): result = compose(DENTIST_CATEGORY, MERCHANT_DRMEERA, TRIGGER_RESEARCH) body_l = result["body"].lower() assert "cure" not in body_l assert "guaranteed" not in body_l print("PASS: no taboo terms in dentist output") def test_compose_returns_required_keys(): result = compose(DENTIST_CATEGORY, MERCHANT_DRMEERA, TRIGGER_RESEARCH) for key in ("body", "cta", "rationale"): assert key in result, f"Missing key: {key}" print("PASS: all required keys present") if __name__ == "__main__": test_research_digest_compose() test_perf_dip_compose() test_recall_customer_facing() test_no_taboo_terms() test_compose_returns_required_keys() print("\nAll compose tests passed!")