fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
190
backend/tests/test_email_service.py
Normal file
190
backend/tests/test_email_service.py
Normal file
@@ -0,0 +1,190 @@
|
||||
"""
|
||||
Tests fuer den Email-Service.
|
||||
|
||||
Testet:
|
||||
- EmailService Klasse
|
||||
- SMTP Verbindung (mit Mock)
|
||||
- Messenger-Benachrichtigungen
|
||||
- Jitsi-Einladungen
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from email_service import EmailService, EmailResult
|
||||
|
||||
|
||||
class TestEmailService:
|
||||
"""Tests fuer die EmailService Klasse."""
|
||||
|
||||
def test_init_default_values(self):
|
||||
"""Test: Service wird mit Default-Werten initialisiert."""
|
||||
service = EmailService()
|
||||
|
||||
# Default ist 'mailpit' in Docker, 'localhost' lokal - beides akzeptieren
|
||||
assert service.host in ("localhost", "mailpit")
|
||||
assert service.port == 1025
|
||||
# from_name kann "BreakPilot" oder "BreakPilot Dev" sein (dev environment)
|
||||
assert service.from_name in ("BreakPilot", "BreakPilot Dev")
|
||||
assert service.from_addr == "noreply@breakpilot.app"
|
||||
|
||||
def test_init_custom_values(self):
|
||||
"""Test: Service wird mit benutzerdefinierten Werten initialisiert."""
|
||||
service = EmailService(
|
||||
host="smtp.example.com",
|
||||
port=587,
|
||||
username="user",
|
||||
password="pass",
|
||||
from_name="Custom",
|
||||
from_addr="custom@example.com",
|
||||
use_tls=True
|
||||
)
|
||||
|
||||
assert service.host == "smtp.example.com"
|
||||
assert service.port == 587
|
||||
assert service.username == "user"
|
||||
assert service.password == "pass"
|
||||
assert service.from_name == "Custom"
|
||||
assert service.from_addr == "custom@example.com"
|
||||
assert service.use_tls is True
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_email_success(self, mock_smtp):
|
||||
"""Test: Email wird erfolgreich gesendet."""
|
||||
mock_instance = MagicMock()
|
||||
mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_instance)
|
||||
mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_email(
|
||||
to_email="test@example.com",
|
||||
subject="Test",
|
||||
body_text="Test Body"
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
assert result.recipient == "test@example.com"
|
||||
assert result.sent_at is not None
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_email_with_html(self, mock_smtp):
|
||||
"""Test: Email mit HTML wird gesendet."""
|
||||
mock_instance = MagicMock()
|
||||
mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_instance)
|
||||
mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_email(
|
||||
to_email="test@example.com",
|
||||
subject="Test",
|
||||
body_text="Plain text",
|
||||
body_html="<h1>HTML</h1>"
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_email_failure(self, mock_smtp):
|
||||
"""Test: Fehler beim Email-Versand wird behandelt."""
|
||||
import smtplib
|
||||
mock_smtp.side_effect = smtplib.SMTPException("Connection failed")
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_email(
|
||||
to_email="test@example.com",
|
||||
subject="Test",
|
||||
body_text="Test Body"
|
||||
)
|
||||
|
||||
assert result.success is False
|
||||
assert result.error is not None
|
||||
assert "SMTP" in result.error
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_messenger_notification(self, mock_smtp):
|
||||
"""Test: Messenger-Benachrichtigung wird gesendet."""
|
||||
mock_instance = MagicMock()
|
||||
mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_instance)
|
||||
mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_messenger_notification(
|
||||
to_email="parent@example.com",
|
||||
to_name="Max Mustermann",
|
||||
sender_name="Frau Lehrerin",
|
||||
message_content="Bitte bringen Sie morgen das Buch mit."
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
assert result.recipient == "parent@example.com"
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_jitsi_invitation(self, mock_smtp):
|
||||
"""Test: Jitsi-Einladung wird gesendet."""
|
||||
mock_instance = MagicMock()
|
||||
mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_instance)
|
||||
mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_jitsi_invitation(
|
||||
to_email="parent@example.com",
|
||||
to_name="Max Mustermann",
|
||||
organizer_name="Frau Lehrerin",
|
||||
meeting_title="Elterngespraech",
|
||||
meeting_date="20. Dezember 2024",
|
||||
meeting_time="14:00 Uhr",
|
||||
jitsi_url="https://meet.jit.si/BreakPilot-test123"
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
assert result.recipient == "parent@example.com"
|
||||
|
||||
@patch('email_service.smtplib.SMTP')
|
||||
def test_send_jitsi_invitation_with_additional_info(self, mock_smtp):
|
||||
"""Test: Jitsi-Einladung mit zusaetzlichen Infos wird gesendet."""
|
||||
mock_instance = MagicMock()
|
||||
mock_smtp.return_value.__enter__ = MagicMock(return_value=mock_instance)
|
||||
mock_smtp.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
service = EmailService()
|
||||
result = service.send_jitsi_invitation(
|
||||
to_email="parent@example.com",
|
||||
to_name="Max Mustermann",
|
||||
organizer_name="Frau Lehrerin",
|
||||
meeting_title="Elterngespraech",
|
||||
meeting_date="20. Dezember 2024",
|
||||
meeting_time="14:00 Uhr",
|
||||
jitsi_url="https://meet.jit.si/BreakPilot-test123",
|
||||
additional_info="Bitte bereiten Sie die Zeugnismappe vor."
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
|
||||
|
||||
class TestEmailResult:
|
||||
"""Tests fuer das EmailResult Dataclass."""
|
||||
|
||||
def test_success_result(self):
|
||||
"""Test: Erfolgreiche Email-Antwort."""
|
||||
result = EmailResult(
|
||||
success=True,
|
||||
message_id="msg-123",
|
||||
recipient="test@example.com",
|
||||
sent_at="2024-12-18T10:00:00"
|
||||
)
|
||||
|
||||
assert result.success is True
|
||||
assert result.message_id == "msg-123"
|
||||
assert result.error is None
|
||||
|
||||
def test_failure_result(self):
|
||||
"""Test: Fehlgeschlagene Email-Antwort."""
|
||||
result = EmailResult(
|
||||
success=False,
|
||||
error="Connection refused",
|
||||
recipient="test@example.com"
|
||||
)
|
||||
|
||||
assert result.success is False
|
||||
assert result.error == "Connection refused"
|
||||
assert result.sent_at is None
|
||||
Reference in New Issue
Block a user