Refactoring

This commit is contained in:
dahoud
2026-01-31 16:54:46 +00:00
parent ce89face73
commit 9dc9ca591c
85 changed files with 2643 additions and 381 deletions

View File

@@ -0,0 +1,103 @@
package com.lions.dev.config;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.EstablishmentSubscriptionRepository;
import com.lions.dev.repository.EventsRepository;
import com.lions.dev.repository.PasswordResetTokenRepository;
import com.lions.dev.repository.StoryRepository;
import com.lions.dev.service.EmailService;
import com.lions.dev.service.NotificationService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import java.util.Collections;
import java.util.List;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests des jobs planifiés (ScheduledJobs).
* Les dépendances sont mockées pour éviter DB/Kafka ; on vérifie que les méthodes ne lèvent pas et appellent les repos.
*/
@QuarkusTest
class ScheduledJobsTest {
@Inject
ScheduledJobs scheduledJobs;
@InjectMock
StoryRepository storyRepository;
@InjectMock
PasswordResetTokenRepository passwordResetTokenRepository;
@InjectMock
EstablishmentSubscriptionRepository subscriptionRepository;
@InjectMock
EstablishmentRepository establishmentRepository;
@InjectMock
EventsRepository eventsRepository;
@InjectMock
NotificationService notificationService;
@InjectMock
EmailService emailService;
@Test
@DisplayName("deactivateExpiredStories appelle le repository et ne lance pas")
void deactivateExpiredStories_callsRepository() {
when(storyRepository.deactivateExpiredStories()).thenReturn(0);
scheduledJobs.deactivateExpiredStories();
verify(storyRepository).deactivateExpiredStories();
}
@Test
@DisplayName("deleteExpiredPasswordResetTokens appelle le repository et ne lance pas")
void deleteExpiredPasswordResetTokens_callsRepository() {
when(passwordResetTokenRepository.deleteExpiredTokens()).thenReturn(0L);
scheduledJobs.deleteExpiredPasswordResetTokens();
verify(passwordResetTokenRepository).deleteExpiredTokens();
}
@Test
@DisplayName("expireSubscriptionsAndDisableEstablishments sans abonnements expirés ne lance pas")
void expireSubscriptionsAndDisableEstablishments_emptyList_doesNotThrow() {
when(subscriptionRepository.findExpiredActiveSubscriptions()).thenReturn(Collections.emptyList());
scheduledJobs.expireSubscriptionsAndDisableEstablishments();
verify(subscriptionRepository).findExpiredActiveSubscriptions();
}
@Test
@DisplayName("sendEventReminders sans événements dans les fenêtres ne lance pas")
void sendEventReminders_emptyWindows_doesNotThrow() {
when(eventsRepository.findEventsStartingBetween(any(), any())).thenReturn(List.of());
scheduledJobs.sendEventReminders();
verify(eventsRepository, atLeast(1)).findEventsStartingBetween(any(), any());
}
@Test
@DisplayName("sendSubscriptionExpirationWarningEmails sans abonnements J-3 ne lance pas")
void sendSubscriptionExpirationWarningEmails_emptyList_doesNotThrow() {
when(subscriptionRepository.findActiveSubscriptionsExpiringBetween(any(), any()))
.thenReturn(Collections.emptyList());
scheduledJobs.sendSubscriptionExpirationWarningEmails();
verify(subscriptionRepository).findActiveSubscriptionsExpiringBetween(any(), any());
}
}

View File

@@ -0,0 +1,69 @@
package com.lions.dev.service;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import java.time.LocalDateTime;
/**
* Tests du service email (mode mock : pas d'envoi réel).
* Vérifie que les méthodes n'échouent pas et que le contenu est cohérent.
*/
@QuarkusTest
class EmailServiceTest {
@Inject
EmailService emailService;
@Test
@DisplayName("sendPasswordResetEmail ne lance pas d'exception")
void sendPasswordResetEmail_doesNotThrow() {
emailService.sendPasswordResetEmail("test@example.com", "Jean", "token-123");
}
@Test
@DisplayName("sendWelcomeEmail ne lance pas d'exception")
void sendWelcomeEmail_doesNotThrow() {
emailService.sendWelcomeEmail("welcome@example.com", "Marie");
}
@Test
@DisplayName("sendPaymentConfirmationEmail ne lance pas d'exception")
void sendPaymentConfirmationEmail_doesNotThrow() {
emailService.sendPaymentConfirmationEmail(
"manager@example.com", "Paul", "Le Bar du coin", 15_000, "MONTHLY");
}
@Test
@DisplayName("sendEventReminderEmail ne lance pas d'exception")
void sendEventReminderEmail_doesNotThrow() {
emailService.sendEventReminderEmail(
"user@example.com", "Sophie", "Afterwork Jeudi",
LocalDateTime.now().plusHours(1));
}
@Test
@DisplayName("sendSubscriptionExpirationWarningEmail ne lance pas d'exception")
void sendSubscriptionExpirationWarningEmail_doesNotThrow() {
emailService.sendSubscriptionExpirationWarningEmail(
"manager@example.com", "Luc", "Mon Établissement",
LocalDateTime.now().plusDays(3));
}
@Test
@DisplayName("sendBookingConfirmationEmail ne lance pas d'exception")
void sendBookingConfirmationEmail_doesNotThrow() {
emailService.sendBookingConfirmationEmail(
"client@example.com", "Emma", "Le Restaurant",
LocalDateTime.now().plusDays(1), 4);
}
@Test
@DisplayName("sendPaymentFailureEmail ne lance pas d'exception")
void sendPaymentFailureEmail_doesNotThrow() {
emailService.sendPaymentFailureEmail(
"manager@example.com", "Marc", "Établissement XYZ");
}
}

View File

@@ -0,0 +1,138 @@
package com.lions.dev.service;
import com.lions.dev.entity.notification.Notification;
import com.lions.dev.entity.users.Users;
import com.lions.dev.exception.UserNotFoundException;
import com.lions.dev.repository.EventsRepository;
import com.lions.dev.repository.NotificationRepository;
import com.lions.dev.repository.UsersRepository;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@QuarkusTest
class NotificationServiceTest {
@Inject
NotificationService notificationService;
@InjectMock
NotificationRepository notificationRepository;
@InjectMock
UsersRepository usersRepository;
@InjectMock
EventsRepository eventsRepository;
@Test
@DisplayName("getNotificationsByUserId avec utilisateur existant retourne la liste")
void getNotificationsByUserId_userExists_returnsList() {
UUID userId = UUID.randomUUID();
Users user = new Users();
user.setId(userId);
Notification notif = new Notification("Titre", "Message", "event", user);
when(usersRepository.findById(userId)).thenReturn(user);
when(notificationRepository.findByUserId(userId)).thenReturn(List.of(notif));
List<Notification> result = notificationService.getNotificationsByUserId(userId);
assertNotNull(result);
assertEquals(1, result.size());
assertEquals("Titre", result.get(0).getTitle());
verify(usersRepository).findById(userId);
verify(notificationRepository).findByUserId(userId);
}
@Test
@DisplayName("getNotificationsByUserId avec utilisateur inconnu lance UserNotFoundException")
void getNotificationsByUserId_userNotFound_throws() {
UUID userId = UUID.randomUUID();
when(usersRepository.findById(userId)).thenReturn(null);
assertThrows(UserNotFoundException.class, () ->
notificationService.getNotificationsByUserId(userId));
verify(notificationRepository, never()).findByUserId(any());
}
@Test
@DisplayName("createNotification avec données valides persiste et retourne la notification")
void createNotification_validData_persistsAndReturns() {
UUID userId = UUID.randomUUID();
UUID eventId = UUID.randomUUID();
Users user = new Users();
user.setId(userId);
when(usersRepository.findById(userId)).thenReturn(user);
Notification created = notificationService.createNotification(
"Rappel", "L'événement commence bientôt", "reminder", userId, eventId);
assertNotNull(created);
assertEquals("Rappel", created.getTitle());
assertEquals("reminder", created.getType());
}
@Test
@DisplayName("createNotification avec userId inconnu lance UserNotFoundException")
void createNotification_unknownUser_throws() {
UUID userId = UUID.randomUUID();
when(usersRepository.findById(userId)).thenReturn(null);
assertThrows(UserNotFoundException.class, () ->
notificationService.createNotification("T", "M", "event", userId, null));
}
@Test
@DisplayName("countUnreadNotifications avec utilisateur existant retourne le compte")
void countUnreadNotifications_userExists_returnsCount() {
UUID userId = UUID.randomUUID();
Users user = new Users();
user.setId(userId);
when(usersRepository.findById(userId)).thenReturn(user);
when(notificationRepository.countUnreadByUserId(userId)).thenReturn(3L);
long count = notificationService.countUnreadNotifications(userId);
assertEquals(3L, count);
verify(notificationRepository).countUnreadByUserId(userId);
}
@Test
@DisplayName("countUnreadNotifications avec utilisateur inconnu lance UserNotFoundException")
void countUnreadNotifications_userNotFound_throws() {
UUID userId = UUID.randomUUID();
when(usersRepository.findById(userId)).thenReturn(null);
assertThrows(UserNotFoundException.class, () ->
notificationService.countUnreadNotifications(userId));
}
@Test
@DisplayName("getNotificationsByUserIdWithPagination avec utilisateur existant retourne la page")
void getNotificationsByUserIdWithPagination_userExists_returnsPage() {
UUID userId = UUID.randomUUID();
Users user = new Users();
user.setId(userId);
when(usersRepository.findById(userId)).thenReturn(user);
when(notificationRepository.findByUserIdWithPagination(userId, 0, 10))
.thenReturn(Collections.emptyList());
List<Notification> result = notificationService.getNotificationsByUserIdWithPagination(userId, 0, 10);
assertNotNull(result);
assertTrue(result.isEmpty());
verify(notificationRepository).findByUserIdWithPagination(userId, 0, 10);
}
}

View File

@@ -0,0 +1,183 @@
package com.lions.dev.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lions.dev.dto.response.establishment.InitiateSubscriptionResponseDTO;
import com.lions.dev.entity.establishment.Establishment;
import com.lions.dev.entity.establishment.EstablishmentSubscription;
import com.lions.dev.entity.users.Users;
import com.lions.dev.repository.EstablishmentPaymentRepository;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.EstablishmentSubscriptionRepository;
import com.lions.dev.repository.UsersRepository;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import java.util.Optional;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@QuarkusTest
class WavePaymentServiceTest {
@Inject
WavePaymentService wavePaymentService;
@InjectMock
EstablishmentRepository establishmentRepository;
@InjectMock
EstablishmentSubscriptionRepository subscriptionRepository;
@InjectMock
EstablishmentPaymentRepository paymentRepository;
@InjectMock
UsersRepository usersRepository;
@InjectMock
EmailService emailService;
private static final ObjectMapper objectMapper = new ObjectMapper();
@Test
@DisplayName("initiatePayment avec établissement inconnu lance IllegalArgumentException")
void initiatePayment_unknownEstablishment_throws() {
UUID establishmentId = UUID.randomUUID();
when(establishmentRepository.findById(establishmentId)).thenReturn(null);
assertThrows(IllegalArgumentException.class, () ->
wavePaymentService.initiatePayment(establishmentId, "MONTHLY", "+221771234567"));
}
@Test
@DisplayName("initiatePayment avec établissement valide retourne un DTO avec paymentUrl")
void initiatePayment_validEstablishment_returnsDto() {
UUID establishmentId = UUID.randomUUID();
Establishment establishment = new Establishment();
establishment.setId(establishmentId);
establishment.setName("Le Bar Test");
when(establishmentRepository.findById(establishmentId)).thenReturn(establishment);
InitiateSubscriptionResponseDTO result = wavePaymentService.initiatePayment(
establishmentId, "MONTHLY", "+221771234567");
assertNotNull(result);
assertNotNull(result.getPaymentUrl());
assertTrue(result.getPaymentUrl().contains("checkout") || result.getPaymentUrl().contains("test"));
assertEquals("MONTHLY", result.getPlan());
}
@Test
@DisplayName("hasActiveSubscription retourne false quand aucun abonnement actif")
void hasActiveSubscription_noActive_returnsFalse() {
UUID establishmentId = UUID.randomUUID();
when(subscriptionRepository.findActiveByEstablishmentId(establishmentId)).thenReturn(Optional.empty());
boolean result = wavePaymentService.hasActiveSubscription(establishmentId);
assertFalse(result);
}
@Test
@DisplayName("hasActiveSubscription retourne true quand abonnement actif existe")
void hasActiveSubscription_hasActive_returnsTrue() {
UUID establishmentId = UUID.randomUUID();
EstablishmentSubscription sub = new EstablishmentSubscription();
sub.setEstablishmentId(establishmentId);
sub.setStatus(EstablishmentSubscription.STATUS_ACTIVE);
when(subscriptionRepository.findActiveByEstablishmentId(establishmentId)).thenReturn(Optional.of(sub));
boolean result = wavePaymentService.hasActiveSubscription(establishmentId);
assertTrue(result);
}
@Test
@DisplayName("handleWebhook payment.completed active l'établissement et envoie l'email de confirmation")
void handleWebhook_paymentCompleted_activatesAndSendsEmail() throws Exception {
String sessionId = "wave-session-123";
UUID establishmentId = UUID.randomUUID();
Establishment establishment = new Establishment();
establishment.setId(establishmentId);
establishment.setName("Bar Test");
establishment.setIsActive(false);
Users manager = new Users();
manager.setId(UUID.randomUUID());
manager.setEmail("manager@test.com");
manager.setFirstName("Jean");
manager.setActive(false);
establishment.setManager(manager);
EstablishmentSubscription sub = new EstablishmentSubscription();
sub.setId(UUID.randomUUID());
sub.setEstablishmentId(establishmentId);
sub.setPlan(EstablishmentSubscription.PLAN_MONTHLY);
sub.setStatus(EstablishmentSubscription.STATUS_PENDING);
sub.setAmountXof(15_000);
when(subscriptionRepository.findByWaveSessionId(sessionId)).thenReturn(Optional.of(sub));
when(establishmentRepository.findById(establishmentId)).thenReturn(establishment);
when(usersRepository.findById(manager.getId())).thenReturn(manager);
when(paymentRepository.findByWaveSessionId(sessionId)).thenReturn(Optional.of(new com.lions.dev.entity.establishment.EstablishmentPayment()));
String payload = """
{"type":"payment.completed","data":{"id":"%s"}}
""".formatted(sessionId);
var node = objectMapper.readTree(payload);
wavePaymentService.handleWebhook(node);
verify(emailService).sendPaymentConfirmationEmail(
eq("manager@test.com"),
eq("Jean"),
eq("Bar Test"),
eq(15_000),
eq("MONTHLY")
);
}
@Test
@DisplayName("handleWebhook payment.failed envoie l'email d'échec")
void handleWebhook_paymentFailed_sendsFailureEmail() throws Exception {
String sessionId = "wave-session-fail";
UUID establishmentId = UUID.randomUUID();
Establishment establishment = new Establishment();
establishment.setId(establishmentId);
establishment.setName("Bar Fail");
Users manager = new Users();
manager.setId(UUID.randomUUID());
manager.setEmail("manager@fail.com");
manager.setFirstName("Paul");
establishment.setManager(manager);
EstablishmentSubscription sub = new EstablishmentSubscription();
sub.setId(UUID.randomUUID());
sub.setEstablishmentId(establishmentId);
sub.setStatus(EstablishmentSubscription.STATUS_PENDING);
when(subscriptionRepository.findByWaveSessionId(sessionId)).thenReturn(Optional.of(sub));
when(establishmentRepository.findById(establishmentId)).thenReturn(establishment);
when(usersRepository.findById(manager.getId())).thenReturn(manager);
when(paymentRepository.findByWaveSessionId(sessionId)).thenReturn(Optional.of(new com.lions.dev.entity.establishment.EstablishmentPayment()));
String payload = """
{"type":"payment.failed","data":{"id":"%s"}}
""".formatted(sessionId);
var node = objectMapper.readTree(payload);
wavePaymentService.handleWebhook(node);
verify(emailService).sendPaymentFailureEmail(
eq("manager@fail.com"),
eq("Paul"),
eq("Bar Fail")
);
}
}