"""Integration-Tests für WhatsApp/Telegram-Webhook-Flows.""" import hashlib import hmac from datetime import datetime from unittest.mock import MagicMock, patch import pytest from flask import Flask from src.app import create_app from src.queue.worker import verarbeite_submission, worker_loop from src.routes.admin import admin_bp from src.routes.telegram import telegram_bp from src.routes.whatsapp import whatsapp_bp from src.services.game_service import GameService @pytest.fixture() def flask_app() -> Flask: """Erstellt Flask-App mit allen Blueprints.""" app = create_app() app.queue_handler = MagicMock() app.queue_handler.queue_size.return_value = 0 app.register_blueprint(whatsapp_bp, name="whatsapp_int") app.register_blueprint(telegram_bp, name="telegram_int") app.register_blueprint(admin_bp, name="admin_int", url_prefix="/admin") return app class TestWebhookIntegration: """Tests für Webhook-Integration.""" def test_whatsapp_post_mit_gueltiger_signatur(self, flask_app: Flask) -> None: """WhatsApp POST mit gültiger Signatur -> 200, Submission in Queue.""" with patch("src.routes.whatsapp.verify_whatsapp_signature", return_value=True): response = flask_app.test_client().post( "/webhook/whatsapp", data="""{ "object":"whatsapp", "entry":[{"id":"123","changes":[{"value":{"messages":[{"id":"msg001","timestamp":1234567890,"from":"+491****1234","text":{"body":"hallo"}}]}}]}]}""".encode(), headers={"X-Hub-Signature-256": "sha256=test"}, content_type="application/json", ) assert response.status_code == 200 data = response.get_json() assert data["status"] == "accepted" flask_app.queue_handler.enqueue.assert_called_once() def test_whatsapp_post_mit_ungueltiger_signatur(self, flask_app: Flask) -> None: """WhatsApp POST mit ungültiger Signatur -> 401.""" with patch("src.routes.whatsapp.verify_whatsapp_signature", return_value=False): response = flask_app.test_client().post( "/webhook/whatsapp", data=b'{"object":"whatsapp","entry":[{"id":"123","changes":[{"value":{"messages":[{"id":"msg999","timestamp":1234567890,"from":"+491****5678","text":{"body":"test"}}]}}]}]}', headers={"X-Hub-Signature-256": "sha256=fake"}, content_type="application/json", ) assert response.status_code == 401 data = response.get_json() assert "error" in data class TestTelegramIntegration: """Tests für Telegram-Integration.""" def test_telegram_post_mit_gueltigem_payload(self, flask_app: Flask) -> None: """Telegram POST mit gültigem Payload -> 200.""" response = flask_app.test_client().post( "/webhook/telegram", json={"message": {"message_id": "123", "chat": {"id": "456"}, "text": "Hallo"}}, ) assert response.status_code == 200 data = response.get_json() assert data["status"] == "accepted" flask_app.queue_handler.enqueue.assert_called_once() class TestWorkerIntegration: """Tests für Worker-Integration.""" def test_vollstaendiger_flow_whatsapp(self, flask_app: Flask) -> None: """Vollstaendiger Flow: WhatsApp POST -> Worker verarbeitet -> Status 'erledigt'.""" mock_qh = flask_app.queue_handler mock_submission = MagicMock() mock_submission.message_id = "msg001" mock_submission.zeitstempel = datetime(2024, 1, 1) mock_submission.absender = "+491****7890" mock_submission.text = "suche Catan" mock_submission.status = "neu" mock_submission.ergebnis = None mock_submission.enqueue.return_value = "stream_id" call_count = [0] def dequeue_side_effect(count: int = 5) -> list: call_count[0] += 1 if call_count[0] <= 1: return [mock_submission] return [] mock_qh.dequeue.side_effect = dequeue_side_effect with ( patch("src.queue.worker.verarbeite_submission", return_value=True) as mock_verarb, patch("src.queue.worker.time.sleep", return_value=None), ): worker_loop(mock_qh, poll_interval=0, batch_size=5, max_iterations=2) assert mock_verarb.call_count == 1 assert mock_qh.mark_done.call_count == 1 def test_vollstaendiger_flow_telegram(self, flask_app: Flask) -> None: """Vollstaendiger Flow: Telegram POST -> Worker verarbeitet -> Status 'erledigt'.""" mock_qh = flask_app.queue_handler mock_submission = MagicMock() mock_submission.message_id = "msg002" mock_submission.zeitstempel = datetime(2024, 1, 1) mock_submission.absender = "@user123" mock_submission.text = "hilfe" mock_submission.status = "neu" mock_submission.ergebnis = None call_count = [0] def dequeue_side_effect(count: int = 5) -> list: call_count[0] += 1 if call_count[0] <= 1: return [mock_submission] return [] mock_qh.dequeue.side_effect = dequeue_side_effect with ( patch("src.queue.worker.verarbeite_submission", return_value=True) as mock_verarb, patch("src.queue.worker.time.sleep", return_value=None), ): worker_loop(mock_qh, poll_interval=0, batch_size=5, max_iterations=2) assert mock_verarb.call_count == 1 assert mock_qh.mark_done.call_count == 1