Files
notytex/backend/tests/unit/test_email_service.py
Bertrand Benjamin 2b08eb534a Migration v1 (Flask) -> v2 (FastAPI + Vue.js) complétée
 Changements majeurs:
- Suppression complète du code Flask legacy
- Migration backend FastAPI vers racine /backend
- Migration frontend Vue.js vers racine /frontend
- Suppression de notytex-v2/ (code monté à la racine)

 Validations:
- Backend démarre correctement (port 8000)
- API /api/v2/health répond healthy
- 99/99 tests unitaires passent
- Frontend configuré avec proxy Vite

📝 Documentation:
- README.md réécrit pour v2
- Instructions de démarrage mises à jour
- .gitignore adapté pour backend/frontend/

🎯 Architecture finale:
notytex/
├── backend/     # FastAPI + SQLAlchemy + Pydantic
├── frontend/    # Vue 3 + Vite + TailwindCSS
├── docs/        # Documentation
└── school_management.db  # Base de données (inchangée)

Jalon 6 complété: Application v2 prête pour utilisation!
2025-11-25 21:09:47 +01:00

201 lines
6.4 KiB
Python

"""
Tests unitaires pour le service d'email.
"""
import pytest
from infrastructure.external.email_service import EmailService, SMTPConfig
class TestSMTPConfig:
"""Tests pour la configuration SMTP."""
def test_valid_localhost_config(self):
"""Configuration locale valide sans authentification."""
config = SMTPConfig(
host="localhost",
port=1025,
username="",
password="",
use_tls=False,
from_name="Test",
from_address="test@example.com"
)
assert config.is_valid() is True
def test_valid_production_config(self):
"""Configuration production valide avec authentification."""
config = SMTPConfig(
host="smtp.gmail.com",
port=587,
username="user@gmail.com",
password="password123",
use_tls=True,
from_name="Notytex",
from_address="notytex@school.com"
)
assert config.is_valid() is True
def test_invalid_config_missing_host(self):
"""Configuration invalide sans host."""
config = SMTPConfig(
host="",
port=587,
username="user",
password="pass",
use_tls=True,
from_name="Test",
from_address="test@example.com"
)
assert config.is_valid() is False
def test_invalid_config_missing_from_address(self):
"""Configuration invalide sans adresse expéditeur."""
config = SMTPConfig(
host="smtp.gmail.com",
port=587,
username="user",
password="pass",
use_tls=True,
from_name="Test",
from_address=""
)
assert config.is_valid() is False
def test_invalid_production_config_no_auth(self):
"""Configuration production invalide sans authentification."""
config = SMTPConfig(
host="smtp.gmail.com",
port=587,
username="",
password="",
use_tls=True,
from_name="Test",
from_address="test@example.com"
)
assert config.is_valid() is False
class TestEmailService:
"""Tests pour le service d'email."""
def test_service_not_configured(self):
"""Service non configuré."""
service = EmailService()
assert service.is_configured() is False
def test_service_with_config(self):
"""Service avec configuration valide."""
config = SMTPConfig(
host="localhost",
port=1025,
username="",
password="",
use_tls=False,
from_name="Test",
from_address="test@example.com"
)
service = EmailService(config)
assert service.is_configured() is True
def test_set_config(self):
"""Définir la configuration après initialisation."""
service = EmailService()
assert service.is_configured() is False
config = SMTPConfig(
host="localhost",
port=1025,
username="",
password="",
use_tls=False,
from_name="Test",
from_address="test@example.com"
)
service.set_config(config)
assert service.is_configured() is True
def test_send_email_not_configured(self):
"""Envoi d'email échoue si non configuré."""
service = EmailService()
result = service.send_email(
to_emails=["test@example.com"],
subject="Test",
html_body="<p>Test</p>"
)
assert result['success'] is False
assert 'incomplète' in result['error']
def test_from_database_config(self):
"""Création du service depuis la configuration DB."""
db_config = {
'email.smtp_host': 'localhost',
'email.smtp_port': '1025',
'email.username': '',
'email.password': '',
'email.use_tls': 'false',
'email.from_name': 'Notytex',
'email.from_address': 'test@example.com'
}
service = EmailService.from_database_config(db_config)
assert service.is_configured() is True
assert service.config.host == 'localhost'
assert service.config.port == 1025
assert service.config.from_name == 'Notytex'
def test_from_database_config_defaults(self):
"""Valeurs par défaut pour la configuration DB."""
db_config = {}
service = EmailService.from_database_config(db_config)
assert service.config.port == 587
assert service.config.use_tls is True
assert service.config.from_name == 'Notytex'
class TestEmailValidation:
"""Tests pour la validation d'adresses email."""
def test_validate_valid_emails(self):
"""Validation d'adresses valides."""
emails = ["test@example.com", "user.name@domain.org", "a@b.co"]
result = EmailService.validate_email_addresses(emails)
assert result['valid_count'] == 3
assert result['invalid_count'] == 0
assert len(result['valid']) == 3
def test_validate_invalid_emails(self):
"""Validation d'adresses invalides."""
emails = ["invalid", "no-at-sign", "@nodomain", "space @test.com"]
result = EmailService.validate_email_addresses(emails)
assert result['valid_count'] == 0
assert result['invalid_count'] == 4
def test_validate_mixed_emails(self):
"""Validation d'un mélange d'adresses."""
emails = ["valid@test.com", "invalid", "another@valid.org"]
result = EmailService.validate_email_addresses(emails)
assert result['valid_count'] == 2
assert result['invalid_count'] == 1
assert "valid@test.com" in result['valid']
assert "invalid" in result['invalid']
def test_validate_empty_emails(self):
"""Validation d'une liste vide."""
result = EmailService.validate_email_addresses([])
assert result['valid_count'] == 0
assert result['invalid_count'] == 0
def test_validate_whitespace_emails(self):
"""Les espaces sont supprimés lors de la validation."""
emails = [" test@example.com ", " user@domain.org"]
result = EmailService.validate_email_addresses(emails)
assert result['valid_count'] == 2
assert "test@example.com" in result['valid']
assert "user@domain.org" in result['valid']