from __future__ import annotations import pytest from backend.app.core.config import settings from backend.app.services.campaign_vectorizer import FEATURE_KEYS from backend.app.services.blueprint_engine import build_blueprint, score_campaign_for_segment from backend.app.services.campaign_vectorizer import extract_campaign_features from backend.app.services.gmm_engine import run_gmm_clustering from backend.app.services.rag_optimizer import optimize_campaign @pytest.fixture(autouse=True) def _force_heuristic_mode(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(settings, "ollama_api_key", "") def test_heuristic_vectorizer_changes_with_campaign_text() -> None: evidence_text = ( "Phase 3 randomized trial data demonstrated improved progression-free survival, " "safety, and endpoint performance in eligible oncology patients." ) access_text = ( "Digital omnichannel launch with budget-friendly access messaging, rapid adoption, " "and broad patient reach across regional accounts." ) evidence_features = extract_campaign_features(evidence_text)["normalized_features"] access_features = extract_campaign_features(access_text)["normalized_features"] total_delta = sum(abs(evidence_features[key] - access_features[key]) for key in evidence_features) assert total_delta > 0.5 assert evidence_features["trial_phase_relevance"] > access_features["trial_phase_relevance"] assert access_features["channel_preference"] > evidence_features["channel_preference"] def test_optimize_campaign_returns_offline_improvements() -> None: campaign_text = "Broad brand campaign with limited clinical detail and minimal access context." optimized = optimize_campaign(campaign_text, target_cluster=2) assert optimized["original_text"] == campaign_text assert optimized["optimized_text"] != campaign_text assert optimized["improvements"] assert optimized["alignment_score"] is not None def test_build_blueprint_returns_complete_payload() -> None: blueprint = build_blueprint( 2, campaign_text="Budget-sensitive launch planning for a digital-first oncology message.", core_message="Refined positioning for the segment.", ) assert blueprint["segmentId"] == "2" assert blueprint["segmentName"] assert blueprint["coreClinicalMessage"] == "Refined positioning for the segment." assert len(blueprint["optimalChannels"]) == 4 assert len(blueprint["ragInjections"]) == 3 assert len(blueprint["tacticalSteps"]) == 3 assert len(blueprint["modifications"]) == 3 assert blueprint["gapSummary"]["largestGap"] is not None def test_score_campaign_for_segment_accepts_string_cluster_ids() -> None: result = score_campaign_for_segment( "c2", "Randomized study evidence with endpoint detail for specialist stakeholders.", ) assert result["cluster_id"] == 2 assert result["status"] in {"approved", "rejected"} assert len(result["alternatives"]) == 3 assert result["feature_gaps"] def test_score_campaign_uses_fitted_gmm_artifacts_when_supplied() -> None: records = [ { key: min(0.95, max(0.05, ((idx + offset) % 9) / 8.0)) for offset, key in enumerate(FEATURE_KEYS) } for idx in range(24) ] artifacts = run_gmm_clustering(records, min_k=2, feature_names=list(FEATURE_KEYS)) result = score_campaign_for_segment( 0, "Phase 3 oncology launch with digital KOL education and access proof.", gmm_artifacts=artifacts, ) assert result["statistical_artifacts"] == "fitted_gmm_covariance" assert result["statistical_artifacts_reason"] == "" assert len(result["heatmap"]["ranking"]) == artifacts["k"]