package dev.lions.unionflow.server.service; import static org.assertj.core.api.Assertions.*; import dev.lions.unionflow.server.api.dto.suggestion.request.CreateSuggestionRequest; import dev.lions.unionflow.server.api.dto.suggestion.response.SuggestionResponse; import dev.lions.unionflow.server.entity.Suggestion; import dev.lions.unionflow.server.entity.SuggestionVote; import dev.lions.unionflow.server.repository.SuggestionRepository; import dev.lions.unionflow.server.repository.SuggestionVoteRepository; import io.quarkus.test.junit.QuarkusTest; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.NotFoundException; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.*; /** * Tests unitaires pour SuggestionService * * @author UnionFlow Team * @version 1.0 * @since 2025-12-18 */ @QuarkusTest @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class SuggestionServiceTest { @Inject SuggestionService suggestionService; @Inject SuggestionRepository suggestionRepository; @Inject SuggestionVoteRepository suggestionVoteRepository; private Suggestion testSuggestion; private UUID utilisateurId1; private UUID utilisateurId2; @BeforeEach @Transactional void setupTestData() { utilisateurId1 = UUID.randomUUID(); utilisateurId2 = UUID.randomUUID(); // Créer une suggestion de test testSuggestion = Suggestion.builder() .utilisateurId(utilisateurId1) .utilisateurNom("Test User") .titre("Suggestion de Test") .description("Description de test") .statut("NOUVELLE") .nbVotes(0) .nbCommentaires(0) .nbVues(0) .build(); testSuggestion.setDateCreation(LocalDateTime.now()); testSuggestion.setDateSoumission(LocalDateTime.now()); testSuggestion.setActif(true); suggestionRepository.persist(testSuggestion); } @AfterEach @Transactional void cleanupTestData() { // Supprimer tous les votes if (testSuggestion != null && testSuggestion.getId() != null) { List votes = suggestionVoteRepository.listerVotesParSuggestion(testSuggestion.getId()); votes.forEach(vote -> suggestionVoteRepository.delete(vote)); } // Supprimer la suggestion if (testSuggestion != null && testSuggestion.getId() != null) { Suggestion suggestionToDelete = suggestionRepository.findById(testSuggestion.getId()); if (suggestionToDelete != null) { suggestionRepository.delete(suggestionToDelete); } } } @Test @Order(1) @DisplayName("Devrait lister toutes les suggestions") void testListerSuggestions() { // When List suggestions = suggestionService.listerSuggestions(); // Then assertThat(suggestions).isNotNull(); assertThat(suggestions).isNotEmpty(); // Vérifier que notre suggestion de test est dans la liste assertThat(suggestions) .anyMatch(s -> s.getId().equals(testSuggestion.getId())); } @Test @Order(2) @DisplayName("Devrait créer une nouvelle suggestion") void testCreerSuggestion() { // Given CreateSuggestionRequest request = CreateSuggestionRequest.builder() .utilisateurId(utilisateurId2) .utilisateurNom("Nouvel Utilisateur") .titre("Nouvelle Suggestion") .description("Description de la nouvelle suggestion") .categorie("FEATURE") .prioriteEstimee("HAUTE") .build(); // When SuggestionResponse created = suggestionService.creerSuggestion(request); // Then assertThat(created).isNotNull(); assertThat(created.getId()).isNotNull(); assertThat(created.getTitre()).isEqualTo("Nouvelle Suggestion"); assertThat(created.getStatut()).isEqualTo("NOUVELLE"); assertThat(created.getNbVotes()).isEqualTo(0); assertThat(created.getNbCommentaires()).isEqualTo(0); assertThat(created.getDateSoumission()).isNotNull(); // Cleanup Suggestion createdEntity = suggestionRepository.findById(created.getId()); if (createdEntity != null) { suggestionRepository.delete(createdEntity); } } @Test @Order(3) @DisplayName("Devrait permettre à un utilisateur de voter pour une suggestion") void testVoterPourSuggestion() { // Given UUID suggestionId = testSuggestion.getId(); int nbVotesInitial = testSuggestion.getNbVotes() != null ? testSuggestion.getNbVotes() : 0; // When suggestionService.voterPourSuggestion(suggestionId, utilisateurId2); // Then // Vérifier que le vote a été créé assertThat(suggestionVoteRepository.aDejaVote(suggestionId, utilisateurId2)).isTrue(); // Vérifier que le compteur de votes a été mis à jour Suggestion updatedSuggestion = suggestionRepository.findById(suggestionId); assertThat(updatedSuggestion.getNbVotes()).isEqualTo(nbVotesInitial + 1); } @Test @Order(4) @DisplayName("Ne devrait pas permettre à un utilisateur de voter deux fois") void testNePasPermettreVoteMultiple() { // Given UUID suggestionId = testSuggestion.getId(); // Premier vote suggestionService.voterPourSuggestion(suggestionId, utilisateurId2); // When/Then - Tentative de vote multiple assertThatThrownBy( () -> suggestionService.voterPourSuggestion(suggestionId, utilisateurId2)) .isInstanceOf(IllegalStateException.class) .hasMessageContaining("déjà voté"); } @Test @Order(5) @DisplayName("Devrait lever une exception si la suggestion n'existe pas") void testVoterPourSuggestionInexistante() { // Given UUID suggestionInexistante = UUID.randomUUID(); // When/Then assertThatThrownBy( () -> suggestionService.voterPourSuggestion(suggestionInexistante, utilisateurId2)) .isInstanceOf(NotFoundException.class) .hasMessageContaining("non trouvée"); } @Test @Order(6) @DisplayName("Devrait synchroniser le compteur de votes avec la base de données") void testSynchronisationCompteurVotes() { // Given UUID suggestionId = testSuggestion.getId(); // Créer plusieurs votes directement dans la base SuggestionVote vote1 = SuggestionVote.builder() .suggestionId(suggestionId) .utilisateurId(utilisateurId1) .dateVote(LocalDateTime.now()) .build(); vote1.setActif(true); suggestionVoteRepository.persist(vote1); SuggestionVote vote2 = SuggestionVote.builder() .suggestionId(suggestionId) .utilisateurId(utilisateurId2) .dateVote(LocalDateTime.now()) .build(); vote2.setActif(true); suggestionVoteRepository.persist(vote2); // Mettre à jour le compteur manuellement (simulation d'un état désynchronisé) testSuggestion.setNbVotes(0); suggestionRepository.update(testSuggestion); // When - Voter via le service (qui doit synchroniser) UUID utilisateurId3 = UUID.randomUUID(); suggestionService.voterPourSuggestion(suggestionId, utilisateurId3); // Then - Le compteur doit être synchronisé avec la base (2 votes existants + 1 // nouveau = 3) Suggestion updatedSuggestion = suggestionRepository.findById(suggestionId); assertThat(updatedSuggestion.getNbVotes()).isEqualTo(3); } @Test @Order(7) @DisplayName("Devrait obtenir les statistiques des suggestions") void testObtenirStatistiques() { // When Map stats = suggestionService.obtenirStatistiques(); // Then assertThat(stats).isNotNull(); assertThat(stats).containsKey("totalSuggestions"); assertThat(stats).containsKey("suggestionsImplementees"); assertThat(stats).containsKey("totalVotes"); assertThat(stats).containsKey("contributeursActifs"); assertThat(stats.get("totalSuggestions")).isInstanceOf(Long.class); assertThat((Long) stats.get("totalSuggestions")).isGreaterThanOrEqualTo(1); } }