veza/veza-backend-api/internal/services/email_service_password_reset_test.go
2025-12-12 21:34:34 -05:00

143 lines
6 KiB
Go

package services
import (
"os"
"strings"
"testing"
"veza-backend-api/internal/database"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)
// setupTestEmailServiceForPasswordReset crée un EmailService de test
func setupTestEmailServiceForPasswordReset(_ *testing.T) *EmailService {
// Créer un Database wrapper minimal pour les tests
// Note: On ne peut pas vraiment tester l'envoi d'email sans un serveur SMTP réel
// Donc on va tester la construction de l'email et la logique, mais pas l'envoi réel
testDB := &database.Database{}
logger, _ := zap.NewDevelopment()
// Définir des variables d'environnement de test si nécessaire
os.Setenv("FRONTEND_URL", "http://localhost:5173")
os.Setenv("SMTP_HOST", "localhost")
os.Setenv("SMTP_PORT", "587")
os.Setenv("FROM_EMAIL", "test@veza.com")
os.Setenv("FROM_NAME", "Veza Test")
return NewEmailService(testDB, logger)
}
// TestEmailService_SendPasswordResetEmail_URLGeneration tests URL generation
func TestEmailService_SendPasswordResetEmail_URLGeneration(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
// Test avec FRONTEND_URL défini
os.Setenv("FRONTEND_URL", "https://app.veza.com")
resetURL := service.buildPasswordResetEmail("https://app.veza.com/reset-password?token=test-token-123")
assert.Contains(t, resetURL, "https://app.veza.com/reset-password?token=test-token-123")
assert.Contains(t, resetURL, "Reset Password")
assert.Contains(t, resetURL, "This link will expire in 1 hour")
}
// TestEmailService_SendPasswordResetEmail_DefaultURL tests default URL when FRONTEND_URL is not set
func TestEmailService_SendPasswordResetEmail_DefaultURL(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
// Supprimer FRONTEND_URL pour tester la valeur par défaut
os.Unsetenv("FRONTEND_URL")
// Construire l'URL manuellement pour tester
resetURL := "http://localhost:5173/reset-password?token=test-token-456"
emailBody := service.buildPasswordResetEmail(resetURL)
assert.Contains(t, emailBody, "http://localhost:5173/reset-password?token=test-token-456")
assert.Contains(t, emailBody, "Reset Password")
assert.Contains(t, emailBody, "This link will expire in 1 hour")
assert.Contains(t, emailBody, "If you didn't request this, please ignore this email")
}
// TestEmailService_BuildPasswordResetEmail_HTMLContent tests HTML email content
func TestEmailService_BuildPasswordResetEmail_HTMLContent(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
resetURL := "https://example.com/reset-password?token=abc123"
emailBody := service.buildPasswordResetEmail(resetURL)
// Vérifier que le HTML contient les éléments requis
assert.Contains(t, emailBody, "<!DOCTYPE html>")
assert.Contains(t, emailBody, "<html>")
assert.Contains(t, emailBody, "Reset your password")
assert.Contains(t, emailBody, "Reset Password")
assert.Contains(t, emailBody, resetURL)
assert.Contains(t, emailBody, "This link will expire in 1 hour")
assert.Contains(t, emailBody, "If you didn't request this, please ignore this email")
assert.Contains(t, emailBody, "You requested to reset your Veza account password")
}
// TestEmailService_BuildPasswordResetEmail_ExpirationMessage tests expiration message
func TestEmailService_BuildPasswordResetEmail_ExpirationMessage(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
resetURL := "https://example.com/reset-password?token=xyz789"
emailBody := service.buildPasswordResetEmail(resetURL)
// Vérifier que le message d'expiration est présent
assert.Contains(t, emailBody, "This link will expire in 1 hour")
// Vérifier que le message de sécurité est présent
assert.Contains(t, emailBody, "If you didn't request this, please ignore this email")
// Vérifier que le lien est présent deux fois (bouton et texte)
resetCount := strings.Count(emailBody, resetURL)
assert.GreaterOrEqual(t, resetCount, 2, "Reset URL should appear at least twice (button and text)")
}
// TestEmailService_BuildPasswordResetEmail_TemplateFallback tests template fallback on error
func TestEmailService_BuildPasswordResetEmail_TemplateFallback(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
// Test avec une URL valide - le template devrait fonctionner
resetURL := "https://example.com/reset-password?token=test-token"
emailBody := service.buildPasswordResetEmail(resetURL)
// Le template devrait être parsé correctement
assert.Contains(t, emailBody, resetURL)
assert.Contains(t, emailBody, "<html>")
// Vérifier que le fallback n'est pas utilisé (le template devrait être parsé)
assert.NotContains(t, emailBody, "Click here to reset your password:")
}
// TestEmailService_BuildPasswordResetEmail_ContainsToken tests that token is included in URL
func TestEmailService_BuildPasswordResetEmail_ContainsToken(t *testing.T) {
service := setupTestEmailServiceForPasswordReset(t)
testToken := "test-reset-token-12345"
resetURL := "https://example.com/reset-password?token=" + testToken
emailBody := service.buildPasswordResetEmail(resetURL)
// Vérifier que le token est présent dans l'email
assert.Contains(t, emailBody, testToken)
assert.Contains(t, emailBody, "reset-password?token="+testToken)
}
// TestEmailService_SendPasswordResetEmail_Subject tests email subject
func TestEmailService_SendPasswordResetEmail_Subject(t *testing.T) {
// Cette méthode teste indirectement que le sujet est correct
// En regardant le code, le sujet est "Reset your Veza password"
// On ne peut pas tester directement l'envoi sans SMTP, mais on peut vérifier la logique
service := setupTestEmailServiceForPasswordReset(t)
// Vérifier que la méthode existe et peut être appelée
// Note: On ne peut pas vraiment tester l'envoi sans mock SMTP
// Mais on peut vérifier que buildPasswordResetEmail fonctionne
resetURL := "https://example.com/reset-password?token=test"
emailBody := service.buildPasswordResetEmail(resetURL)
require.NotEmpty(t, emailBody, "Email body should not be empty")
assert.Contains(t, emailBody, "Reset your password")
}