""" Tests für RelevanceProfile Model. """ import pytest from datetime import datetime from alerts_agent.models.relevance_profile import RelevanceProfile, PriorityItem class TestPriorityItem: """Tests für PriorityItem.""" def test_create_minimal(self): """Test minimale Erstellung.""" item = PriorityItem(label="Test Topic") assert item.label == "Test Topic" assert item.weight == 0.5 # Default assert item.keywords == [] assert item.description is None def test_create_full(self): """Test vollständige Erstellung.""" item = PriorityItem( label="Inklusion", weight=0.9, keywords=["inklusiv", "Förderbedarf"], description="Inklusive Bildung in Schulen", ) assert item.label == "Inklusion" assert item.weight == 0.9 assert "inklusiv" in item.keywords assert item.description is not None def test_to_dict(self): """Test Serialisierung.""" item = PriorityItem(label="Test", weight=0.8, keywords=["kw1", "kw2"]) data = item.to_dict() assert data["label"] == "Test" assert data["weight"] == 0.8 assert data["keywords"] == ["kw1", "kw2"] def test_from_dict(self): """Test Deserialisierung.""" data = {"label": "Test", "weight": 0.7, "keywords": ["test"]} item = PriorityItem.from_dict(data) assert item.label == "Test" assert item.weight == 0.7 class TestRelevanceProfile: """Tests für RelevanceProfile.""" def test_create_empty(self): """Test leeres Profil.""" profile = RelevanceProfile() assert profile.id is not None assert profile.priorities == [] assert profile.exclusions == [] assert profile.positive_examples == [] assert profile.negative_examples == [] def test_add_priority(self): """Test Priorität hinzufügen.""" profile = RelevanceProfile() profile.add_priority("Datenschutz", weight=0.85) assert len(profile.priorities) == 1 assert profile.priorities[0].label == "Datenschutz" assert profile.priorities[0].weight == 0.85 def test_add_exclusion(self): """Test Ausschluss hinzufügen.""" profile = RelevanceProfile() profile.add_exclusion("Stellenanzeige") profile.add_exclusion("Werbung") assert len(profile.exclusions) == 2 assert "Stellenanzeige" in profile.exclusions assert "Werbung" in profile.exclusions def test_no_duplicate_exclusions(self): """Test keine doppelten Ausschlüsse.""" profile = RelevanceProfile() profile.add_exclusion("Test") profile.add_exclusion("Test") assert len(profile.exclusions) == 1 def test_add_positive_example(self): """Test positives Beispiel hinzufügen.""" profile = RelevanceProfile() profile.add_positive_example( title="Gutes Beispiel", url="https://example.com", reason="Relevant für Thema X", ) assert len(profile.positive_examples) == 1 assert profile.positive_examples[0]["title"] == "Gutes Beispiel" assert profile.positive_examples[0]["reason"] == "Relevant für Thema X" def test_add_negative_example(self): """Test negatives Beispiel hinzufügen.""" profile = RelevanceProfile() profile.add_negative_example( title="Schlechtes Beispiel", url="https://example.com", reason="Werbung", ) assert len(profile.negative_examples) == 1 def test_examples_limited_to_20(self): """Test Beispiele auf 20 begrenzt.""" profile = RelevanceProfile() for i in range(25): profile.add_positive_example( title=f"Example {i}", url=f"https://example.com/{i}", ) assert len(profile.positive_examples) == 20 # Sollte die neuesten behalten assert "Example 24" in profile.positive_examples[-1]["title"] def test_update_from_feedback_positive(self): """Test Feedback Update (positiv).""" profile = RelevanceProfile() profile.update_from_feedback( alert_title="Relevant Article", alert_url="https://example.com", is_relevant=True, reason="Sehr relevant", ) assert len(profile.positive_examples) == 1 assert profile.total_kept == 1 assert profile.total_scored == 1 def test_update_from_feedback_negative(self): """Test Feedback Update (negativ).""" profile = RelevanceProfile() profile.update_from_feedback( alert_title="Irrelevant Article", alert_url="https://example.com", is_relevant=False, reason="Werbung", ) assert len(profile.negative_examples) == 1 assert profile.total_dropped == 1 assert profile.total_scored == 1 class TestPromptContext: """Tests für Prompt-Kontext Generierung.""" def test_empty_profile_prompt(self): """Test Prompt für leeres Profil.""" profile = RelevanceProfile() context = profile.get_prompt_context() assert "Relevanzprofil" in context # Leeres Profil hat keine Prioritäten/Ausschlüsse assert "Prioritäten" not in context def test_priorities_in_prompt(self): """Test Prioritäten im Prompt.""" profile = RelevanceProfile() profile.add_priority("Inklusion", weight=0.9, description="Sehr wichtig") context = profile.get_prompt_context() assert "Inklusion" in context assert "Sehr wichtig" in context def test_exclusions_in_prompt(self): """Test Ausschlüsse im Prompt.""" profile = RelevanceProfile() profile.add_exclusion("Stellenanzeige") profile.add_exclusion("Werbung") context = profile.get_prompt_context() assert "Stellenanzeige" in context assert "Werbung" in context assert "Ausschlüsse" in context def test_examples_in_prompt(self): """Test Beispiele im Prompt.""" profile = RelevanceProfile() profile.add_positive_example( title="Gutes Beispiel", url="https://example.com", reason="Relevant", ) context = profile.get_prompt_context() assert "Gutes Beispiel" in context assert "relevante Alerts" in context class TestDefaultEducationProfile: """Tests für das Standard-Bildungsprofil.""" def test_create_default_profile(self): """Test Default-Profil Erstellung.""" profile = RelevanceProfile.create_default_education_profile() assert len(profile.priorities) > 0 assert len(profile.exclusions) > 0 assert len(profile.policies) > 0 def test_default_priorities(self): """Test Default-Prioritäten enthalten Bildungsthemen.""" profile = RelevanceProfile.create_default_education_profile() labels = [p.label for p in profile.priorities] assert "Inklusion" in labels assert "Datenschutz Schule" in labels assert "Schulrecht Bayern" in labels def test_default_exclusions(self): """Test Default-Ausschlüsse.""" profile = RelevanceProfile.create_default_education_profile() assert "Stellenanzeige" in profile.exclusions assert "Werbung" in profile.exclusions def test_default_policies(self): """Test Default-Policies.""" profile = RelevanceProfile.create_default_education_profile() assert profile.policies.get("prefer_german_sources") is True assert "max_age_days" in profile.policies class TestSerialization: """Tests für Serialisierung.""" def test_to_dict(self): """Test Konvertierung zu Dict.""" profile = RelevanceProfile() profile.add_priority("Test", weight=0.7) profile.add_exclusion("Exclude") data = profile.to_dict() assert "id" in data assert len(data["priorities"]) == 1 assert "Exclude" in data["exclusions"] assert "created_at" in data def test_from_dict(self): """Test Erstellung aus Dict.""" data = { "id": "test-id", "priorities": [{"label": "Test", "weight": 0.8, "keywords": [], "description": None}], "exclusions": ["Exclude"], "positive_examples": [], "negative_examples": [], "policies": {"key": "value"}, "created_at": "2024-01-15T10:00:00", "updated_at": "2024-01-15T10:00:00", "total_scored": 100, "total_kept": 60, "total_dropped": 40, "accuracy_estimate": None, } profile = RelevanceProfile.from_dict(data) assert profile.id == "test-id" assert len(profile.priorities) == 1 assert profile.total_scored == 100 def test_round_trip(self): """Test Serialisierung/Deserialisierung Roundtrip.""" original = RelevanceProfile.create_default_education_profile() original.add_positive_example("Test", "https://test.com") data = original.to_dict() restored = RelevanceProfile.from_dict(data) assert restored.id == original.id assert len(restored.priorities) == len(original.priorities) assert len(restored.positive_examples) == len(original.positive_examples)