""" Tests für AlertItem Model. """ import pytest from datetime import datetime from alerts_agent.models.alert_item import AlertItem, AlertSource, AlertStatus class TestAlertItemCreation: """Tests für AlertItem Erstellung.""" def test_create_minimal_alert(self): """Test minimale Alert-Erstellung.""" alert = AlertItem(title="Test Alert", url="https://example.com/article") assert alert.title == "Test Alert" assert alert.url == "https://example.com/article" assert alert.id is not None assert len(alert.id) == 36 # UUID format assert alert.status == AlertStatus.NEW assert alert.source == AlertSource.GOOGLE_ALERTS_RSS def test_create_full_alert(self): """Test vollständige Alert-Erstellung.""" alert = AlertItem( source=AlertSource.GOOGLE_ALERTS_EMAIL, topic_label="Inklusion Bayern", title="Neue Inklusions-Richtlinie", url="https://example.com/inklusion", snippet="Die neue Richtlinie für inklusive Bildung...", lang="de", published_at=datetime(2024, 1, 15, 10, 30), ) assert alert.source == AlertSource.GOOGLE_ALERTS_EMAIL assert alert.topic_label == "Inklusion Bayern" assert alert.lang == "de" assert alert.published_at.year == 2024 def test_url_hash_generated(self): """Test dass URL Hash automatisch generiert wird.""" alert = AlertItem( title="Test", url="https://example.com/test" ) assert alert.url_hash is not None assert len(alert.url_hash) == 16 # 16 hex chars def test_canonical_url_generated(self): """Test dass kanonische URL generiert wird.""" alert = AlertItem( title="Test", url="https://EXAMPLE.com/path/" ) # Sollte lowercase und ohne trailing slash sein assert alert.canonical_url == "https://example.com/path" class TestURLNormalization: """Tests für URL Normalisierung.""" def test_remove_tracking_params(self): """Test Entfernung von Tracking-Parametern.""" alert = AlertItem( title="Test", url="https://example.com/article?utm_source=google&utm_medium=email&id=123" ) # utm_source und utm_medium sollten entfernt werden, id bleibt assert "utm_source" not in alert.canonical_url assert "utm_medium" not in alert.canonical_url assert "id=123" in alert.canonical_url def test_lowercase_domain(self): """Test Domain wird lowercase.""" alert = AlertItem( title="Test", url="https://WWW.EXAMPLE.COM/Article" ) assert "www.example.com" in alert.canonical_url def test_remove_fragment(self): """Test Fragment wird entfernt.""" alert = AlertItem( title="Test", url="https://example.com/article#section1" ) assert "#" not in alert.canonical_url def test_same_url_same_hash(self): """Test gleiche URL produziert gleichen Hash.""" alert1 = AlertItem(title="Test", url="https://example.com/test") alert2 = AlertItem(title="Test", url="https://example.com/test") assert alert1.url_hash == alert2.url_hash def test_different_url_different_hash(self): """Test verschiedene URLs produzieren verschiedene Hashes.""" alert1 = AlertItem(title="Test", url="https://example.com/test1") alert2 = AlertItem(title="Test", url="https://example.com/test2") assert alert1.url_hash != alert2.url_hash class TestAlertSerialization: """Tests für Serialisierung.""" def test_to_dict(self): """Test Konvertierung zu Dictionary.""" alert = AlertItem( title="Test Alert", url="https://example.com", topic_label="Test Topic", ) data = alert.to_dict() assert data["title"] == "Test Alert" assert data["url"] == "https://example.com" assert data["topic_label"] == "Test Topic" assert data["source"] == "google_alerts_rss" assert data["status"] == "new" def test_from_dict(self): """Test Erstellung aus Dictionary.""" data = { "id": "test-id-123", "title": "Test Alert", "url": "https://example.com", "source": "google_alerts_email", "status": "scored", "relevance_score": 0.85, } alert = AlertItem.from_dict(data) assert alert.id == "test-id-123" assert alert.title == "Test Alert" assert alert.source == AlertSource.GOOGLE_ALERTS_EMAIL assert alert.status == AlertStatus.SCORED assert alert.relevance_score == 0.85 def test_round_trip(self): """Test Serialisierung und Deserialisierung.""" original = AlertItem( title="Round Trip Test", url="https://example.com/roundtrip", topic_label="Testing", relevance_score=0.75, relevance_decision="KEEP", ) data = original.to_dict() restored = AlertItem.from_dict(data) assert restored.title == original.title assert restored.url == original.url assert restored.relevance_score == original.relevance_score class TestAlertStatus: """Tests für Alert Status.""" def test_status_enum_values(self): """Test Status Enum Werte.""" assert AlertStatus.NEW.value == "new" assert AlertStatus.PROCESSED.value == "processed" assert AlertStatus.DUPLICATE.value == "duplicate" assert AlertStatus.SCORED.value == "scored" assert AlertStatus.REVIEWED.value == "reviewed" assert AlertStatus.ARCHIVED.value == "archived" def test_source_enum_values(self): """Test Source Enum Werte.""" assert AlertSource.GOOGLE_ALERTS_RSS.value == "google_alerts_rss" assert AlertSource.GOOGLE_ALERTS_EMAIL.value == "google_alerts_email" assert AlertSource.MANUAL.value == "manual"