Authentification stable - WIP

This commit is contained in:
DahoudG
2025-09-19 12:35:46 +00:00
parent 63fe107f98
commit 098894bdc1
383 changed files with 13072 additions and 93334 deletions

View File

@@ -0,0 +1,375 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.api.dto.solidarite.aide.AideDTO;
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
import dev.lions.unionflow.server.service.AideService;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mock;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import jakarta.ws.rs.NotFoundException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;
/**
* Tests d'intégration pour AideResource
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-15
*/
@QuarkusTest
@DisplayName("AideResource - Tests d'intégration")
class AideResourceTest {
@Mock
AideService aideService;
private AideDTO aideDTOTest;
private List<AideDTO> listeAidesTest;
@BeforeEach
void setUp() {
// DTO de test
aideDTOTest = new AideDTO();
aideDTOTest.setId(UUID.randomUUID());
aideDTOTest.setNumeroReference("AIDE-2025-TEST01");
aideDTOTest.setTitre("Aide médicale urgente");
aideDTOTest.setDescription("Demande d'aide pour frais médicaux urgents");
aideDTOTest.setTypeAide("MEDICALE");
aideDTOTest.setMontantDemande(new BigDecimal("500000.00"));
aideDTOTest.setStatut("EN_ATTENTE");
aideDTOTest.setPriorite("URGENTE");
aideDTOTest.setMembreDemandeurId(UUID.randomUUID());
aideDTOTest.setAssociationId(UUID.randomUUID());
aideDTOTest.setActif(true);
// Liste de test
listeAidesTest = Arrays.asList(aideDTOTest);
}
@Nested
@DisplayName("Tests des endpoints CRUD")
class CrudEndpointsTests {
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("GET /api/aides - Liste des aides")
void testListerAides() {
// Given
when(aideService.listerAidesActives(0, 20)).thenReturn(listeAidesTest);
// When & Then
given()
.when()
.get("/api/aides")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", is(1))
.body("[0].titre", equalTo("Aide médicale urgente"))
.body("[0].statut", equalTo("EN_ATTENTE"));
}
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("GET /api/aides/{id} - Récupération par ID")
void testObtenirAideParId() {
// Given
when(aideService.obtenirAideParId(1L)).thenReturn(aideDTOTest);
// When & Then
given()
.when()
.get("/api/aides/1")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("titre", equalTo("Aide médicale urgente"))
.body("numeroReference", equalTo("AIDE-2025-TEST01"));
}
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("GET /api/aides/{id} - Aide non trouvée")
void testObtenirAideParId_NonTrouvee() {
// Given
when(aideService.obtenirAideParId(999L)).thenThrow(new NotFoundException("Demande d'aide non trouvée"));
// When & Then
given()
.when()
.get("/api/aides/999")
.then()
.statusCode(404)
.contentType(ContentType.JSON)
.body("error", equalTo("Demande d'aide non trouvée"));
}
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("POST /api/aides - Création d'aide")
void testCreerAide() {
// Given
when(aideService.creerAide(any(AideDTO.class))).thenReturn(aideDTOTest);
// When & Then
given()
.contentType(ContentType.JSON)
.body(aideDTOTest)
.when()
.post("/api/aides")
.then()
.statusCode(201)
.contentType(ContentType.JSON)
.body("titre", equalTo("Aide médicale urgente"))
.body("numeroReference", equalTo("AIDE-2025-TEST01"));
}
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("PUT /api/aides/{id} - Mise à jour d'aide")
void testMettreAJourAide() {
// Given
AideDTO aideMiseAJour = new AideDTO();
aideMiseAJour.setTitre("Titre modifié");
aideMiseAJour.setDescription("Description modifiée");
when(aideService.mettreAJourAide(eq(1L), any(AideDTO.class))).thenReturn(aideMiseAJour);
// When & Then
given()
.contentType(ContentType.JSON)
.body(aideMiseAJour)
.when()
.put("/api/aides/1")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("titre", equalTo("Titre modifié"));
}
}
@Nested
@DisplayName("Tests des endpoints métier")
class EndpointsMetierTests {
@Test
@TestSecurity(user = "evaluateur", roles = {"evaluateur_aide"})
@DisplayName("POST /api/aides/{id}/approuver - Approbation d'aide")
void testApprouverAide() {
// Given
AideDTO aideApprouvee = new AideDTO();
aideApprouvee.setStatut("APPROUVEE");
aideApprouvee.setMontantApprouve(new BigDecimal("400000.00"));
when(aideService.approuverAide(eq(1L), any(BigDecimal.class), anyString()))
.thenReturn(aideApprouvee);
Map<String, Object> approbationData = Map.of(
"montantApprouve", "400000.00",
"commentaires", "Aide approuvée après évaluation"
);
// When & Then
given()
.contentType(ContentType.JSON)
.body(approbationData)
.when()
.post("/api/aides/1/approuver")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("statut", equalTo("APPROUVEE"));
}
@Test
@TestSecurity(user = "evaluateur", roles = {"evaluateur_aide"})
@DisplayName("POST /api/aides/{id}/rejeter - Rejet d'aide")
void testRejeterAide() {
// Given
AideDTO aideRejetee = new AideDTO();
aideRejetee.setStatut("REJETEE");
aideRejetee.setRaisonRejet("Dossier incomplet");
when(aideService.rejeterAide(eq(1L), anyString())).thenReturn(aideRejetee);
Map<String, String> rejetData = Map.of(
"raisonRejet", "Dossier incomplet"
);
// When & Then
given()
.contentType(ContentType.JSON)
.body(rejetData)
.when()
.post("/api/aides/1/rejeter")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("statut", equalTo("REJETEE"));
}
@Test
@TestSecurity(user = "tresorier", roles = {"tresorier"})
@DisplayName("POST /api/aides/{id}/verser - Versement d'aide")
void testMarquerCommeVersee() {
// Given
AideDTO aideVersee = new AideDTO();
aideVersee.setStatut("VERSEE");
aideVersee.setMontantVerse(new BigDecimal("400000.00"));
when(aideService.marquerCommeVersee(eq(1L), any(BigDecimal.class), anyString(), anyString()))
.thenReturn(aideVersee);
Map<String, Object> versementData = Map.of(
"montantVerse", "400000.00",
"modeVersement", "MOBILE_MONEY",
"numeroTransaction", "TXN123456789"
);
// When & Then
given()
.contentType(ContentType.JSON)
.body(versementData)
.when()
.post("/api/aides/1/verser")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("statut", equalTo("VERSEE"));
}
}
@Nested
@DisplayName("Tests des endpoints de recherche")
class EndpointsRechercheTests {
@Test
@TestSecurity(user = "membre", roles = {"membre"})
@DisplayName("GET /api/aides/statut/{statut} - Filtrage par statut")
void testListerAidesParStatut() {
// Given
when(aideService.listerAidesParStatut(StatutAide.EN_ATTENTE, 0, 20))
.thenReturn(listeAidesTest);
// When & Then
given()
.when()
.get("/api/aides/statut/EN_ATTENTE")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", is(1))
.body("[0].statut", equalTo("EN_ATTENTE"));
}
@Test
@TestSecurity(user = "membre", roles = {"membre"})
@DisplayName("GET /api/aides/membre/{membreId} - Aides d'un membre")
void testListerAidesParMembre() {
// Given
when(aideService.listerAidesParMembre(1L, 0, 20)).thenReturn(listeAidesTest);
// When & Then
given()
.when()
.get("/api/aides/membre/1")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", is(1));
}
@Test
@TestSecurity(user = "membre", roles = {"membre"})
@DisplayName("GET /api/aides/recherche - Recherche textuelle")
void testRechercherAides() {
// Given
when(aideService.rechercherAides("médical", 0, 20)).thenReturn(listeAidesTest);
// When & Then
given()
.queryParam("q", "médical")
.when()
.get("/api/aides/recherche")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", is(1));
}
@Test
@TestSecurity(user = "admin", roles = {"admin"})
@DisplayName("GET /api/aides/statistiques - Statistiques")
void testObtenirStatistiques() {
// Given
Map<String, Object> statistiques = Map.of(
"total", 100L,
"enAttente", 25L,
"approuvees", 50L,
"versees", 20L
);
when(aideService.obtenirStatistiquesGlobales()).thenReturn(statistiques);
// When & Then
given()
.when()
.get("/api/aides/statistiques")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("total", equalTo(100))
.body("enAttente", equalTo(25))
.body("approuvees", equalTo(50))
.body("versees", equalTo(20));
}
}
@Nested
@DisplayName("Tests de sécurité")
class SecurityTests {
@Test
@DisplayName("Accès non authentifié - 401")
void testAccesNonAuthentifie() {
given()
.when()
.get("/api/aides")
.then()
.statusCode(401);
}
@Test
@TestSecurity(user = "membre", roles = {"membre"})
@DisplayName("Accès non autorisé pour approbation - 403")
void testAccesNonAutorisePourApprobation() {
Map<String, Object> approbationData = Map.of(
"montantApprouve", "400000.00",
"commentaires", "Test"
);
given()
.contentType(ContentType.JSON)
.body(approbationData)
.when()
.post("/api/aides/1/approuver")
.then()
.statusCode(403);
}
}
}

View File

@@ -0,0 +1,329 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.api.dto.finance.CotisationDTO;
import dev.lions.unionflow.server.entity.Cotisation;
import dev.lions.unionflow.server.entity.Membre;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
/**
* Tests d'intégration pour CotisationResource
* Teste tous les endpoints REST de l'API cotisations
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-15
*/
@QuarkusTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@DisplayName("Tests d'intégration - API Cotisations")
class CotisationResourceTest {
private static Long membreTestId;
private static Long cotisationTestId;
private static String numeroReferenceTest;
@BeforeEach
@Transactional
void setUp() {
// Nettoyage et création des données de test
Cotisation.deleteAll();
Membre.deleteAll();
// Création d'un membre de test
Membre membreTest = new Membre();
membreTest.setNumeroMembre("MBR-TEST-001");
membreTest.setNom("Dupont");
membreTest.setPrenom("Jean");
membreTest.setEmail("jean.dupont@test.com");
membreTest.setTelephone("+225070123456");
membreTest.setDateNaissance(LocalDate.of(1985, 5, 15));
membreTest.setActif(true);
membreTest.persist();
membreTestId = membreTest.id;
}
@Test
@org.junit.jupiter.api.Order(1)
@DisplayName("POST /api/cotisations - Création d'une cotisation")
void testCreateCotisation() {
CotisationDTO nouvelleCotisation = new CotisationDTO();
nouvelleCotisation.setMembreId(UUID.fromString(membreTestId.toString()));
nouvelleCotisation.setTypeCotisation("MENSUELLE");
nouvelleCotisation.setMontantDu(new BigDecimal("25000.00"));
nouvelleCotisation.setDateEcheance(LocalDate.now().plusDays(30));
nouvelleCotisation.setDescription("Cotisation mensuelle janvier 2025");
nouvelleCotisation.setPeriode("Janvier 2025");
nouvelleCotisation.setAnnee(2025);
nouvelleCotisation.setMois(1);
given()
.contentType(ContentType.JSON)
.body(nouvelleCotisation)
.when()
.post("/api/cotisations")
.then()
.statusCode(201)
.body("numeroReference", notNullValue())
.body("membreId", equalTo(membreTestId.toString()))
.body("typeCotisation", equalTo("MENSUELLE"))
.body("montantDu", equalTo(25000.00f))
.body("montantPaye", equalTo(0.0f))
.body("statut", equalTo("EN_ATTENTE"))
.body("codeDevise", equalTo("XOF"))
.body("annee", equalTo(2025))
.body("mois", equalTo(1));
}
@Test
@org.junit.jupiter.api.Order(2)
@DisplayName("GET /api/cotisations - Liste des cotisations")
void testGetAllCotisations() {
given()
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/cotisations")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@org.junit.jupiter.api.Order(3)
@DisplayName("GET /api/cotisations/{id} - Récupération par ID")
void testGetCotisationById() {
// Créer d'abord une cotisation
CotisationDTO cotisation = createTestCotisation();
cotisationTestId = Long.valueOf(cotisation.getId().toString());
given()
.pathParam("id", cotisationTestId)
.when()
.get("/api/cotisations/{id}")
.then()
.statusCode(200)
.body("id", equalTo(cotisationTestId.toString()))
.body("typeCotisation", equalTo("MENSUELLE"));
}
@Test
@org.junit.jupiter.api.Order(4)
@DisplayName("GET /api/cotisations/reference/{numeroReference} - Récupération par référence")
void testGetCotisationByReference() {
// Utiliser la cotisation créée précédemment
if (numeroReferenceTest == null) {
CotisationDTO cotisation = createTestCotisation();
numeroReferenceTest = cotisation.getNumeroReference();
}
given()
.pathParam("numeroReference", numeroReferenceTest)
.when()
.get("/api/cotisations/reference/{numeroReference}")
.then()
.statusCode(200)
.body("numeroReference", equalTo(numeroReferenceTest))
.body("typeCotisation", equalTo("MENSUELLE"));
}
@Test
@org.junit.jupiter.api.Order(5)
@DisplayName("PUT /api/cotisations/{id} - Mise à jour d'une cotisation")
void testUpdateCotisation() {
// Créer une cotisation si nécessaire
if (cotisationTestId == null) {
CotisationDTO cotisation = createTestCotisation();
cotisationTestId = Long.valueOf(cotisation.getId().toString());
}
CotisationDTO cotisationMiseAJour = new CotisationDTO();
cotisationMiseAJour.setTypeCotisation("TRIMESTRIELLE");
cotisationMiseAJour.setMontantDu(new BigDecimal("75000.00"));
cotisationMiseAJour.setDescription("Cotisation trimestrielle Q1 2025");
cotisationMiseAJour.setObservations("Mise à jour du type de cotisation");
given()
.contentType(ContentType.JSON)
.pathParam("id", cotisationTestId)
.body(cotisationMiseAJour)
.when()
.put("/api/cotisations/{id}")
.then()
.statusCode(200)
.body("typeCotisation", equalTo("TRIMESTRIELLE"))
.body("montantDu", equalTo(75000.00f))
.body("observations", equalTo("Mise à jour du type de cotisation"));
}
@Test
@org.junit.jupiter.api.Order(6)
@DisplayName("GET /api/cotisations/membre/{membreId} - Cotisations d'un membre")
void testGetCotisationsByMembre() {
given()
.pathParam("membreId", membreTestId)
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/cotisations/membre/{membreId}")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@org.junit.jupiter.api.Order(7)
@DisplayName("GET /api/cotisations/statut/{statut} - Cotisations par statut")
void testGetCotisationsByStatut() {
given()
.pathParam("statut", "EN_ATTENTE")
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/cotisations/statut/{statut}")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@org.junit.jupiter.api.Order(8)
@DisplayName("GET /api/cotisations/en-retard - Cotisations en retard")
void testGetCotisationsEnRetard() {
given()
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/cotisations/en-retard")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@org.junit.jupiter.api.Order(9)
@DisplayName("GET /api/cotisations/recherche - Recherche avancée")
void testRechercherCotisations() {
given()
.queryParam("membreId", membreTestId)
.queryParam("statut", "EN_ATTENTE")
.queryParam("annee", 2025)
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/cotisations/recherche")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@org.junit.jupiter.api.Order(10)
@DisplayName("GET /api/cotisations/stats - Statistiques des cotisations")
void testGetStatistiquesCotisations() {
given()
.when()
.get("/api/cotisations/stats")
.then()
.statusCode(200)
.body("totalCotisations", notNullValue())
.body("cotisationsPayees", notNullValue())
.body("cotisationsEnRetard", notNullValue())
.body("tauxPaiement", notNullValue());
}
@Test
@org.junit.jupiter.api.Order(11)
@DisplayName("DELETE /api/cotisations/{id} - Suppression d'une cotisation")
void testDeleteCotisation() {
// Créer une cotisation si nécessaire
if (cotisationTestId == null) {
CotisationDTO cotisation = createTestCotisation();
cotisationTestId = Long.valueOf(cotisation.getId().toString());
}
given()
.pathParam("id", cotisationTestId)
.when()
.delete("/api/cotisations/{id}")
.then()
.statusCode(204);
// Vérifier que la cotisation est marquée comme annulée
given()
.pathParam("id", cotisationTestId)
.when()
.get("/api/cotisations/{id}")
.then()
.statusCode(200)
.body("statut", equalTo("ANNULEE"));
}
@Test
@DisplayName("GET /api/cotisations/{id} - Cotisation inexistante")
void testGetCotisationByIdNotFound() {
given()
.pathParam("id", 99999L)
.when()
.get("/api/cotisations/{id}")
.then()
.statusCode(404)
.body("error", equalTo("Cotisation non trouvée"));
}
@Test
@DisplayName("POST /api/cotisations - Données invalides")
void testCreateCotisationInvalidData() {
CotisationDTO cotisationInvalide = new CotisationDTO();
// Données manquantes ou invalides
cotisationInvalide.setTypeCotisation("");
cotisationInvalide.setMontantDu(new BigDecimal("-100"));
given()
.contentType(ContentType.JSON)
.body(cotisationInvalide)
.when()
.post("/api/cotisations")
.then()
.statusCode(400);
}
/**
* Méthode utilitaire pour créer une cotisation de test
*/
private CotisationDTO createTestCotisation() {
CotisationDTO cotisation = new CotisationDTO();
cotisation.setMembreId(UUID.fromString(membreTestId.toString()));
cotisation.setTypeCotisation("MENSUELLE");
cotisation.setMontantDu(new BigDecimal("25000.00"));
cotisation.setDateEcheance(LocalDate.now().plusDays(30));
cotisation.setDescription("Cotisation de test");
cotisation.setPeriode("Test 2025");
cotisation.setAnnee(2025);
cotisation.setMois(1);
return given()
.contentType(ContentType.JSON)
.body(cotisation)
.when()
.post("/api/cotisations")
.then()
.statusCode(201)
.extract()
.as(CotisationDTO.class);
}
}

View File

@@ -0,0 +1,413 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.entity.Evenement;
import dev.lions.unionflow.server.entity.Evenement.StatutEvenement;
import dev.lions.unionflow.server.entity.Evenement.TypeEvenement;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Organisation;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
/**
* Tests d'intégration pour EvenementResource
*
* Tests complets de l'API REST des événements avec authentification
* et validation des permissions. Optimisé pour l'intégration mobile.
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-15
*/
@QuarkusTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@DisplayName("Tests d'intégration - API Événements")
class EvenementResourceTest {
private static Long evenementTestId;
private static Long organisationTestId;
private static Long membreTestId;
@BeforeAll
@Transactional
static void setupTestData() {
// Créer une organisation de test
Organisation organisation = Organisation.builder()
.nom("Union Test API")
.typeOrganisation("ASSOCIATION")
.statut("ACTIVE")
.email("test-api@union.com")
.telephone("0123456789")
.adresse("123 Rue de Test")
.codePostal("75001")
.ville("Paris")
.pays("France")
.actif(true)
.creePar("test@unionflow.dev")
.dateCreation(LocalDateTime.now())
.build();
organisation.persist();
organisationTestId = organisation.id;
// Créer un membre de test
Membre membre = Membre.builder()
.numeroMembre("UF2025-API01")
.prenom("Marie")
.nom("Martin")
.email("marie.martin@test.com")
.telephone("0987654321")
.dateNaissance(LocalDate.of(1990, 5, 15))
.dateAdhesion(LocalDate.now())
.actif(true)
.organisation(organisation)
.build();
membre.persist();
membreTestId = membre.id;
// Créer un événement de test
Evenement evenement = Evenement.builder()
.titre("Conférence API Test")
.description("Conférence de test pour l'API")
.dateDebut(LocalDateTime.now().plusDays(15))
.dateFin(LocalDateTime.now().plusDays(15).plusHours(2))
.lieu("Centre de conférence Test")
.typeEvenement(TypeEvenement.CONFERENCE)
.statut(StatutEvenement.PLANIFIE)
.capaciteMax(50)
.prix(BigDecimal.valueOf(15.00))
.inscriptionRequise(true)
.visiblePublic(true)
.actif(true)
.organisation(organisation)
.organisateur(membre)
.creePar("test@unionflow.dev")
.dateCreation(LocalDateTime.now())
.build();
evenement.persist();
evenementTestId = evenement.id;
}
@Test
@Order(1)
@DisplayName("GET /api/evenements - Lister événements (authentifié)")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testListerEvenements_Authentifie() {
given()
.when()
.get("/api/evenements")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", greaterThanOrEqualTo(1))
.body("[0].titre", notNullValue())
.body("[0].dateDebut", notNullValue())
.body("[0].statut", notNullValue());
}
@Test
@Order(2)
@DisplayName("GET /api/evenements - Non authentifié")
void testListerEvenements_NonAuthentifie() {
given()
.when()
.get("/api/evenements")
.then()
.statusCode(401);
}
@Test
@Order(3)
@DisplayName("GET /api/evenements/{id} - Récupérer événement")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testObtenirEvenement() {
given()
.pathParam("id", evenementTestId)
.when()
.get("/api/evenements/{id}")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("id", equalTo(evenementTestId.intValue()))
.body("titre", equalTo("Conférence API Test"))
.body("description", equalTo("Conférence de test pour l'API"))
.body("typeEvenement", equalTo("CONFERENCE"))
.body("statut", equalTo("PLANIFIE"))
.body("capaciteMax", equalTo(50))
.body("prix", equalTo(15.0f))
.body("inscriptionRequise", equalTo(true))
.body("visiblePublic", equalTo(true))
.body("actif", equalTo(true));
}
@Test
@Order(4)
@DisplayName("GET /api/evenements/{id} - Événement non trouvé")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testObtenirEvenement_NonTrouve() {
given()
.pathParam("id", 99999)
.when()
.get("/api/evenements/{id}")
.then()
.statusCode(404)
.body("error", equalTo("Événement non trouvé"));
}
@Test
@Order(5)
@DisplayName("POST /api/evenements - Créer événement (organisateur)")
@TestSecurity(user = "marie.martin@test.com", roles = {"ORGANISATEUR_EVENEMENT"})
void testCreerEvenement_Organisateur() {
String nouvelEvenement = String.format("""
{
"titre": "Nouvel Événement Test",
"description": "Description du nouvel événement",
"dateDebut": "%s",
"dateFin": "%s",
"lieu": "Lieu de test",
"typeEvenement": "FORMATION",
"capaciteMax": 30,
"prix": 20.00,
"inscriptionRequise": true,
"visiblePublic": true,
"organisation": {"id": %d},
"organisateur": {"id": %d}
}
""",
LocalDateTime.now().plusDays(20).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
LocalDateTime.now().plusDays(20).plusHours(3).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
organisationTestId,
membreTestId
);
given()
.contentType(ContentType.JSON)
.body(nouvelEvenement)
.when()
.post("/api/evenements")
.then()
.statusCode(201)
.contentType(ContentType.JSON)
.body("titre", equalTo("Nouvel Événement Test"))
.body("typeEvenement", equalTo("FORMATION"))
.body("capaciteMax", equalTo(30))
.body("prix", equalTo(20.0f))
.body("actif", equalTo(true));
}
@Test
@Order(6)
@DisplayName("POST /api/evenements - Permissions insuffisantes")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testCreerEvenement_PermissionsInsuffisantes() {
String nouvelEvenement = """
{
"titre": "Événement Non Autorisé",
"description": "Test permissions",
"dateDebut": "2025-02-15T10:00:00",
"dateFin": "2025-02-15T12:00:00",
"lieu": "Lieu test",
"typeEvenement": "FORMATION"
}
""";
given()
.contentType(ContentType.JSON)
.body(nouvelEvenement)
.when()
.post("/api/evenements")
.then()
.statusCode(403);
}
@Test
@Order(7)
@DisplayName("PUT /api/evenements/{id} - Mettre à jour événement")
@TestSecurity(user = "admin@unionflow.dev", roles = {"ADMIN"})
void testMettreAJourEvenement_Admin() {
String evenementModifie = String.format("""
{
"titre": "Conférence API Test - Modifiée",
"description": "Description mise à jour",
"dateDebut": "%s",
"dateFin": "%s",
"lieu": "Nouveau lieu",
"typeEvenement": "CONFERENCE",
"capaciteMax": 75,
"prix": 25.00,
"inscriptionRequise": true,
"visiblePublic": true
}
""",
LocalDateTime.now().plusDays(16).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
LocalDateTime.now().plusDays(16).plusHours(3).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
);
given()
.pathParam("id", evenementTestId)
.contentType(ContentType.JSON)
.body(evenementModifie)
.when()
.put("/api/evenements/{id}")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("titre", equalTo("Conférence API Test - Modifiée"))
.body("description", equalTo("Description mise à jour"))
.body("lieu", equalTo("Nouveau lieu"))
.body("capaciteMax", equalTo(75))
.body("prix", equalTo(25.0f));
}
@Test
@Order(8)
@DisplayName("GET /api/evenements/a-venir - Événements à venir")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testEvenementsAVenir() {
given()
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/evenements/a-venir")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@Order(9)
@DisplayName("GET /api/evenements/publics - Événements publics (non authentifié)")
void testEvenementsPublics_NonAuthentifie() {
given()
.queryParam("page", 0)
.queryParam("size", 20)
.when()
.get("/api/evenements/publics")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@Order(10)
@DisplayName("GET /api/evenements/recherche - Recherche d'événements")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testRechercherEvenements() {
given()
.queryParam("q", "Conférence")
.queryParam("page", 0)
.queryParam("size", 20)
.when()
.get("/api/evenements/recherche")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@Order(11)
@DisplayName("GET /api/evenements/recherche - Terme de recherche manquant")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testRechercherEvenements_TermeManquant() {
given()
.queryParam("page", 0)
.queryParam("size", 20)
.when()
.get("/api/evenements/recherche")
.then()
.statusCode(400)
.body("error", equalTo("Le terme de recherche est obligatoire"));
}
@Test
@Order(12)
@DisplayName("GET /api/evenements/type/{type} - Événements par type")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testEvenementsParType() {
given()
.pathParam("type", "CONFERENCE")
.queryParam("page", 0)
.queryParam("size", 20)
.when()
.get("/api/evenements/type/{type}")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@Order(13)
@DisplayName("PATCH /api/evenements/{id}/statut - Changer statut")
@TestSecurity(user = "admin@unionflow.dev", roles = {"ADMIN"})
void testChangerStatut() {
given()
.pathParam("id", evenementTestId)
.queryParam("statut", "CONFIRME")
.when()
.patch("/api/evenements/{id}/statut")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("statut", equalTo("CONFIRME"));
}
@Test
@Order(14)
@DisplayName("GET /api/evenements/statistiques - Statistiques")
@TestSecurity(user = "admin@unionflow.dev", roles = {"ADMIN"})
void testObtenirStatistiques() {
given()
.when()
.get("/api/evenements/statistiques")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("total", notNullValue())
.body("actifs", notNullValue())
.body("timestamp", notNullValue());
}
@Test
@Order(15)
@DisplayName("DELETE /api/evenements/{id} - Supprimer événement")
@TestSecurity(user = "admin@unionflow.dev", roles = {"ADMIN"})
void testSupprimerEvenement() {
given()
.pathParam("id", evenementTestId)
.when()
.delete("/api/evenements/{id}")
.then()
.statusCode(204);
}
@Test
@Order(16)
@DisplayName("Pagination - Paramètres valides")
@TestSecurity(user = "marie.martin@test.com", roles = {"MEMBRE"})
void testPagination() {
given()
.queryParam("page", 0)
.queryParam("size", 5)
.queryParam("sort", "titre")
.queryParam("direction", "asc")
.when()
.get("/api/evenements")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
}
}

View File

@@ -0,0 +1,74 @@
package dev.lions.unionflow.server.resource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
/**
* Tests pour HealthResource
*
* @author Lions Dev Team
* @since 2025-01-10
*/
@QuarkusTest
@DisplayName("Tests HealthResource")
class HealthResourceTest {
@Test
@DisplayName("Test GET /api/status - Statut du serveur")
void testGetStatus() {
given()
.when()
.get("/api/status")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("status", equalTo("UP"))
.body("service", equalTo("UnionFlow Server"))
.body("version", equalTo("1.0.0"))
.body("message", equalTo("Serveur opérationnel"))
.body("timestamp", notNullValue());
}
@Test
@DisplayName("Test GET /api/status - Vérification de la structure de la réponse")
void testGetStatusStructure() {
given()
.when()
.get("/api/status")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("$", hasKey("status"))
.body("$", hasKey("service"))
.body("$", hasKey("version"))
.body("$", hasKey("timestamp"))
.body("$", hasKey("message"));
}
@Test
@DisplayName("Test GET /api/status - Vérification du Content-Type")
void testGetStatusContentType() {
given()
.when()
.get("/api/status")
.then()
.statusCode(200)
.contentType("application/json");
}
@Test
@DisplayName("Test GET /api/status - Réponse rapide")
void testGetStatusPerformance() {
given()
.when()
.get("/api/status")
.then()
.statusCode(200)
.time(lessThan(1000L)); // Moins d'1 seconde
}
}

View File

@@ -0,0 +1,322 @@
package dev.lions.unionflow.server.resource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
/**
* Tests d'intégration complets pour MembreResource
* Couvre tous les endpoints et cas d'erreur
*/
@QuarkusTest
@DisplayName("Tests d'intégration complets MembreResource")
class MembreResourceCompleteIntegrationTest {
@Test
@DisplayName("POST /api/membres - Création avec email existant")
void testCreerMembreEmailExistant() {
// Créer un premier membre
String membreJson1 = """
{
"numeroMembre": "UF2025-EXIST01",
"prenom": "Premier",
"nom": "Membre",
"email": "existe@test.com",
"telephone": "221701234567",
"dateNaissance": "1990-05-15",
"dateAdhesion": "2025-01-10",
"actif": true
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson1)
.when()
.post("/api/membres")
.then()
.statusCode(anyOf(is(201), is(400))); // 201 si nouveau, 400 si existe déjà
// Essayer de créer un deuxième membre avec le même email
String membreJson2 = """
{
"numeroMembre": "UF2025-EXIST02",
"prenom": "Deuxieme",
"nom": "Membre",
"email": "existe@test.com",
"telephone": "221701234568",
"dateNaissance": "1985-08-20",
"dateAdhesion": "2025-01-10",
"actif": true
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson2)
.when()
.post("/api/membres")
.then()
.statusCode(400)
.body("message", notNullValue());
}
@Test
@DisplayName("POST /api/membres - Validation des champs obligatoires")
void testCreerMembreValidationChamps() {
// Test avec prénom manquant
String membreSansPrenom = """
{
"nom": "Test",
"email": "test.sans.prenom@test.com",
"telephone": "221701234567"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreSansPrenom)
.when()
.post("/api/membres")
.then()
.statusCode(400);
// Test avec email invalide
String membreEmailInvalide = """
{
"prenom": "Test",
"nom": "Test",
"email": "email-invalide",
"telephone": "221701234567"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreEmailInvalide)
.when()
.post("/api/membres")
.then()
.statusCode(400);
}
@Test
@DisplayName("PUT /api/membres/{id} - Mise à jour membre existant")
void testMettreAJourMembreExistant() {
// D'abord créer un membre
String membreOriginal = """
{
"numeroMembre": "UF2025-UPDATE01",
"prenom": "Original",
"nom": "Membre",
"email": "original.update@test.com",
"telephone": "221701234567",
"dateNaissance": "1990-05-15",
"dateAdhesion": "2025-01-10",
"actif": true
}
""";
// Créer le membre (peut réussir ou échouer si existe déjà)
given()
.contentType(ContentType.JSON)
.body(membreOriginal)
.when()
.post("/api/membres")
.then()
.statusCode(anyOf(is(201), is(400)));
// Essayer de mettre à jour avec ID 1 (peut exister ou non)
String membreMisAJour = """
{
"numeroMembre": "UF2025-UPDATE01",
"prenom": "Modifie",
"nom": "Membre",
"email": "modifie.update@test.com",
"telephone": "221701234567",
"dateNaissance": "1990-05-15",
"dateAdhesion": "2025-01-10",
"actif": true
}
""";
given()
.contentType(ContentType.JSON)
.body(membreMisAJour)
.when()
.put("/api/membres/1")
.then()
.statusCode(anyOf(is(200), is(400))); // 200 si trouvé, 400 si non trouvé
}
@Test
@DisplayName("PUT /api/membres/{id} - Membre inexistant")
void testMettreAJourMembreInexistant() {
String membreJson = """
{
"numeroMembre": "UF2025-INEXIST01",
"prenom": "Inexistant",
"nom": "Membre",
"email": "inexistant@test.com",
"telephone": "221701234567",
"dateNaissance": "1990-05-15",
"dateAdhesion": "2025-01-10",
"actif": true
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson)
.when()
.put("/api/membres/99999")
.then()
.statusCode(400)
.body("message", notNullValue());
}
@Test
@DisplayName("DELETE /api/membres/{id} - Désactiver membre existant")
void testDesactiverMembreExistant() {
// Essayer de désactiver le membre ID 1 (peut exister ou non)
given()
.when()
.delete("/api/membres/1")
.then()
.statusCode(anyOf(is(204), is(404))); // 204 si trouvé, 404 si non trouvé
}
@Test
@DisplayName("DELETE /api/membres/{id} - Membre inexistant")
void testDesactiverMembreInexistant() {
given()
.when()
.delete("/api/membres/99999")
.then()
.statusCode(404)
.body("message", notNullValue());
}
@Test
@DisplayName("GET /api/membres/{id} - Membre existant")
void testObtenirMembreExistant() {
// Essayer d'obtenir le membre ID 1 (peut exister ou non)
given()
.when()
.get("/api/membres/1")
.then()
.statusCode(anyOf(is(200), is(404))); // 200 si trouvé, 404 si non trouvé
}
@Test
@DisplayName("GET /api/membres/{id} - Membre inexistant")
void testObtenirMembreInexistant() {
given()
.when()
.get("/api/membres/99999")
.then()
.statusCode(404)
.body("message", equalTo("Membre non trouvé"));
}
@Test
@DisplayName("GET /api/membres/recherche - Recherche avec terme null")
void testRechercherMembresTermeNull() {
given()
.when()
.get("/api/membres/recherche")
.then()
.statusCode(400)
.body("message", equalTo("Le terme de recherche est requis"));
}
@Test
@DisplayName("GET /api/membres/recherche - Recherche avec terme valide")
void testRechercherMembresTermeValide() {
given()
.queryParam("q", "test")
.when()
.get("/api/membres/recherche")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
}
@Test
@DisplayName("Test des headers HTTP")
void testHeadersHTTP() {
// Test avec différents Accept headers
given()
.accept(ContentType.JSON)
.when()
.get("/api/membres")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
given()
.accept(ContentType.XML)
.when()
.get("/api/membres")
.then()
.statusCode(anyOf(is(200), is(406))); // 200 si supporté, 406 si non supporté
}
@Test
@DisplayName("Test des méthodes HTTP non supportées")
void testMethodesHTTPNonSupportees() {
// OPTIONS peut être supporté ou non
given()
.when()
.options("/api/membres")
.then()
.statusCode(anyOf(is(200), is(405)));
// HEAD peut être supporté ou non
given()
.when()
.head("/api/membres")
.then()
.statusCode(anyOf(is(200), is(405)));
}
@Test
@DisplayName("Test de performance et robustesse")
void testPerformanceEtRobustesse() {
// Test avec une grande quantité de données
StringBuilder largeJson = new StringBuilder();
largeJson.append("{");
largeJson.append("\"prenom\": \"").append("A".repeat(100)).append("\",");
largeJson.append("\"nom\": \"").append("B".repeat(100)).append("\",");
largeJson.append("\"email\": \"large.test@test.com\",");
largeJson.append("\"telephone\": \"221701234567\"");
largeJson.append("}");
given()
.contentType(ContentType.JSON)
.body(largeJson.toString())
.when()
.post("/api/membres")
.then()
.statusCode(anyOf(is(201), is(400))); // Peut réussir ou échouer selon la validation
}
@Test
@DisplayName("Test de gestion des erreurs serveur")
void testGestionErreursServeur() {
// Test avec des données qui peuvent causer des erreurs internes
String jsonMalformed = "{ invalid json }";
given()
.contentType(ContentType.JSON)
.body(jsonMalformed)
.when()
.post("/api/membres")
.then()
.statusCode(400); // Bad Request pour JSON malformé
}
}

View File

@@ -0,0 +1,258 @@
package dev.lions.unionflow.server.resource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
/**
* Tests d'intégration simples pour MembreResource
*
* @author Lions Dev Team
* @since 2025-01-10
*/
@QuarkusTest
@DisplayName("Tests d'intégration simples MembreResource")
class MembreResourceSimpleIntegrationTest {
@Test
@DisplayName("GET /api/membres - Lister tous les membres actifs")
void testListerMembres() {
given()
.when()
.get("/api/membres")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("$", notNullValue());
}
@Test
@DisplayName("GET /api/membres/999 - Membre non trouvé")
void testObtenirMembreNonTrouve() {
given()
.when()
.get("/api/membres/999")
.then()
.statusCode(404)
.contentType(ContentType.JSON)
.body("message", equalTo("Membre non trouvé"));
}
@Test
@DisplayName("POST /api/membres - Données invalides")
void testCreerMembreDonneesInvalides() {
String membreJson = """
{
"prenom": "",
"nom": "",
"email": "email-invalide",
"telephone": "123",
"dateNaissance": "2030-01-01"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson)
.when()
.post("/api/membres")
.then()
.statusCode(400);
}
@Test
@DisplayName("PUT /api/membres/999 - Membre non trouvé")
void testMettreAJourMembreNonTrouve() {
String membreJson = """
{
"prenom": "Pierre",
"nom": "Martin",
"email": "pierre.martin@test.com"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson)
.when()
.put("/api/membres/999")
.then()
.statusCode(400); // Simplement vérifier le code de statut
}
@Test
@DisplayName("DELETE /api/membres/999 - Membre non trouvé")
void testDesactiverMembreNonTrouve() {
given()
.when()
.delete("/api/membres/999")
.then()
.statusCode(404)
.contentType(ContentType.JSON)
.body("message", containsString("Membre non trouvé"));
}
@Test
@DisplayName("GET /api/membres/recherche - Terme manquant")
void testRechercherMembresTermeManquant() {
given()
.when()
.get("/api/membres/recherche")
.then()
.statusCode(400)
.contentType(ContentType.JSON)
.body("message", equalTo("Le terme de recherche est requis"));
}
@Test
@DisplayName("GET /api/membres/recherche - Terme vide")
void testRechercherMembresTermeVide() {
given()
.queryParam("q", " ")
.when()
.get("/api/membres/recherche")
.then()
.statusCode(400)
.contentType(ContentType.JSON)
.body("message", equalTo("Le terme de recherche est requis"));
}
@Test
@DisplayName("GET /api/membres/recherche - Recherche valide")
void testRechercherMembresValide() {
given()
.queryParam("q", "test")
.when()
.get("/api/membres/recherche")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("$", notNullValue());
}
@Test
@DisplayName("GET /api/membres/stats - Statistiques")
void testObtenirStatistiques() {
given()
.when()
.get("/api/membres/stats")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
.body("nombreMembresActifs", notNullValue())
.body("timestamp", notNullValue());
}
@Test
@DisplayName("POST /api/membres - Membre valide")
void testCreerMembreValide() {
String membreJson = """
{
"prenom": "Jean",
"nom": "Dupont",
"email": "jean.dupont.test@example.com",
"telephone": "221701234567",
"dateNaissance": "1990-05-15",
"dateAdhesion": "2025-01-10"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreJson)
.when()
.post("/api/membres")
.then()
.statusCode(anyOf(is(201), is(400))); // 201 si succès, 400 si email existe déjà
}
@Test
@DisplayName("Test des endpoints avec différents content types")
void testContentTypes() {
// Test avec Accept header
given()
.accept(ContentType.JSON)
.when()
.get("/api/membres")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
// Test avec Accept header pour les stats
given()
.accept(ContentType.JSON)
.when()
.get("/api/membres/stats")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
}
@Test
@DisplayName("Test des méthodes HTTP non supportées")
void testMethodesNonSupportees() {
// PATCH n'est pas supporté
given()
.when()
.patch("/api/membres/1")
.then()
.statusCode(405); // Method Not Allowed
}
@Test
@DisplayName("PUT /api/membres/{id} - Mise à jour avec données invalides")
void testMettreAJourMembreAvecDonneesInvalides() {
String membreInvalideJson = """
{
"prenom": "",
"nom": "",
"email": "email-invalide"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreInvalideJson)
.when()
.put("/api/membres/1")
.then()
.statusCode(400);
}
@Test
@DisplayName("POST /api/membres - Données invalides")
void testCreerMembreAvecDonneesInvalides() {
String membreInvalideJson = """
{
"prenom": "",
"nom": "",
"email": "email-invalide"
}
""";
given()
.contentType(ContentType.JSON)
.body(membreInvalideJson)
.when()
.post("/api/membres")
.then()
.statusCode(400);
}
@Test
@DisplayName("GET /api/membres/recherche - Terme avec espaces seulement")
void testRechercherMembresTermeAvecEspacesUniquement() {
given()
.queryParam("q", " ")
.when()
.get("/api/membres/recherche")
.then()
.statusCode(400)
.contentType(ContentType.JSON)
.body("message", equalTo("Le terme de recherche est requis"));
}
}

View File

@@ -0,0 +1,282 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.api.dto.membre.MembreDTO;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.service.MembreService;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;
/**
* Tests pour MembreResource
*
* @author Lions Dev Team
* @since 2025-01-10
*/
@ExtendWith(MockitoExtension.class)
@DisplayName("Tests MembreResource")
class MembreResourceTest {
@InjectMocks
MembreResource membreResource;
@Mock
MembreService membreService;
@Test
@DisplayName("Test de l'existence de la classe MembreResource")
void testMembreResourceExists() {
// Given & When & Then
assertThat(MembreResource.class).isNotNull();
assertThat(membreResource).isNotNull();
}
@Test
@DisplayName("Test de l'annotation Path")
void testPathAnnotation() {
// Given & When & Then
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Path.class))
.isNotNull();
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Path.class).value())
.isEqualTo("/api/membres");
}
@Test
@DisplayName("Test de l'annotation ApplicationScoped")
void testApplicationScopedAnnotation() {
// Given & When & Then
assertThat(MembreResource.class.getAnnotation(jakarta.enterprise.context.ApplicationScoped.class))
.isNotNull();
}
@Test
@DisplayName("Test de l'annotation Produces")
void testProducesAnnotation() {
// Given & When & Then
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Produces.class))
.isNotNull();
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Produces.class).value())
.contains("application/json");
}
@Test
@DisplayName("Test de l'annotation Consumes")
void testConsumesAnnotation() {
// Given & When & Then
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Consumes.class))
.isNotNull();
assertThat(MembreResource.class.getAnnotation(jakarta.ws.rs.Consumes.class).value())
.contains("application/json");
}
@Test
@DisplayName("Test des méthodes du resource")
void testResourceMethods() throws NoSuchMethodException {
// Given & When & Then
assertThat(MembreResource.class.getMethod("listerMembres")).isNotNull();
assertThat(MembreResource.class.getMethod("obtenirMembre", Long.class)).isNotNull();
assertThat(MembreResource.class.getMethod("creerMembre", Membre.class)).isNotNull();
assertThat(MembreResource.class.getMethod("mettreAJourMembre", Long.class, Membre.class)).isNotNull();
assertThat(MembreResource.class.getMethod("desactiverMembre", Long.class)).isNotNull();
assertThat(MembreResource.class.getMethod("rechercherMembres", String.class)).isNotNull();
assertThat(MembreResource.class.getMethod("obtenirStatistiques")).isNotNull();
}
@Test
@DisplayName("Test de la création d'instance")
void testInstanceCreation() {
// Given & When
MembreResource resource = new MembreResource();
// Then
assertThat(resource).isNotNull();
}
@Test
@DisplayName("Test listerMembres")
void testListerMembres() {
// Given
List<Membre> membres = Arrays.asList(
createTestMembre("Jean", "Dupont"),
createTestMembre("Marie", "Martin")
);
List<MembreDTO> membresDTO = Arrays.asList(
createTestMembreDTO("Jean", "Dupont"),
createTestMembreDTO("Marie", "Martin")
);
when(membreService.listerMembresActifs(any(Page.class), any(Sort.class))).thenReturn(membres);
when(membreService.convertToDTOList(membres)).thenReturn(membresDTO);
// When
Response response = membreResource.listerMembres(0, 20, "nom", "asc");
// Then
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isEqualTo(membresDTO);
}
@Test
@DisplayName("Test obtenirMembre")
void testObtenirMembre() {
// Given
Long id = 1L;
Membre membre = createTestMembre("Jean", "Dupont");
when(membreService.trouverParId(id)).thenReturn(Optional.of(membre));
// When
Response response = membreResource.obtenirMembre(id);
// Then
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isEqualTo(membre);
}
@Test
@DisplayName("Test obtenirMembre - membre non trouvé")
void testObtenirMembreNonTrouve() {
// Given
Long id = 999L;
when(membreService.trouverParId(id)).thenReturn(Optional.empty());
// When
Response response = membreResource.obtenirMembre(id);
// Then
assertThat(response.getStatus()).isEqualTo(404);
}
@Test
@DisplayName("Test creerMembre")
void testCreerMembre() {
// Given
MembreDTO membreDTO = createTestMembreDTO("Jean", "Dupont");
Membre membre = createTestMembre("Jean", "Dupont");
Membre membreCreated = createTestMembre("Jean", "Dupont");
membreCreated.id = 1L;
MembreDTO membreCreatedDTO = createTestMembreDTO("Jean", "Dupont");
when(membreService.convertFromDTO(any(MembreDTO.class))).thenReturn(membre);
when(membreService.creerMembre(any(Membre.class))).thenReturn(membreCreated);
when(membreService.convertToDTO(any(Membre.class))).thenReturn(membreCreatedDTO);
// When
Response response = membreResource.creerMembre(membreDTO);
// Then
assertThat(response.getStatus()).isEqualTo(201);
assertThat(response.getEntity()).isEqualTo(membreCreatedDTO);
}
@Test
@DisplayName("Test mettreAJourMembre")
void testMettreAJourMembre() {
// Given
Long id = 1L;
MembreDTO membreDTO = createTestMembreDTO("Jean", "Dupont");
Membre membre = createTestMembre("Jean", "Dupont");
Membre membreUpdated = createTestMembre("Jean", "Martin");
membreUpdated.id = id;
MembreDTO membreUpdatedDTO = createTestMembreDTO("Jean", "Martin");
when(membreService.convertFromDTO(any(MembreDTO.class))).thenReturn(membre);
when(membreService.mettreAJourMembre(anyLong(), any(Membre.class))).thenReturn(membreUpdated);
when(membreService.convertToDTO(any(Membre.class))).thenReturn(membreUpdatedDTO);
// When
Response response = membreResource.mettreAJourMembre(id, membreDTO);
// Then
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isEqualTo(membreUpdatedDTO);
}
@Test
@DisplayName("Test desactiverMembre")
void testDesactiverMembre() {
// Given
Long id = 1L;
// When
Response response = membreResource.desactiverMembre(id);
// Then
assertThat(response.getStatus()).isEqualTo(204);
}
@Test
@DisplayName("Test rechercherMembres")
void testRechercherMembres() {
// Given
String recherche = "Jean";
List<Membre> membres = Arrays.asList(createTestMembre("Jean", "Dupont"));
List<MembreDTO> membresDTO = Arrays.asList(createTestMembreDTO("Jean", "Dupont"));
when(membreService.rechercherMembres(anyString(), any(Page.class), any(Sort.class))).thenReturn(membres);
when(membreService.convertToDTOList(membres)).thenReturn(membresDTO);
// When
Response response = membreResource.rechercherMembres(recherche, 0, 20, "nom", "asc");
// Then
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isEqualTo(membresDTO);
}
@Test
@DisplayName("Test obtenirStatistiques")
void testObtenirStatistiques() {
// Given
long count = 42L;
when(membreService.compterMembresActifs()).thenReturn(count);
// When
Response response = membreResource.obtenirStatistiques();
// Then
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getEntity()).isInstanceOf(java.util.Map.class);
}
private Membre createTestMembre(String prenom, String nom) {
Membre membre = new Membre();
membre.setPrenom(prenom);
membre.setNom(nom);
membre.setEmail(prenom.toLowerCase() + "." + nom.toLowerCase() + "@test.com");
membre.setTelephone("221701234567");
membre.setDateNaissance(LocalDate.of(1990, 1, 1));
membre.setDateAdhesion(LocalDate.now());
membre.setActif(true);
membre.setNumeroMembre("UF-2025-TEST01");
return membre;
}
private MembreDTO createTestMembreDTO(String prenom, String nom) {
MembreDTO dto = new MembreDTO();
dto.setPrenom(prenom);
dto.setNom(nom);
dto.setEmail(prenom.toLowerCase() + "." + nom.toLowerCase() + "@test.com");
dto.setTelephone("221701234567");
dto.setDateNaissance(LocalDate.of(1990, 1, 1));
dto.setDateAdhesion(LocalDate.now());
dto.setStatut("ACTIF");
dto.setNumeroMembre("UF-2025-TEST01");
dto.setAssociationId(1L);
return dto;
}
}

View File

@@ -0,0 +1,335 @@
package dev.lions.unionflow.server.resource;
import dev.lions.unionflow.server.api.dto.organisation.OrganisationDTO;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
/**
* Tests d'intégration pour OrganisationResource
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-15
*/
@QuarkusTest
class OrganisationResourceTest {
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testCreerOrganisation_Success() {
OrganisationDTO organisation = createTestOrganisationDTO();
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.post("/api/organisations")
.then()
.statusCode(201)
.body("nom", equalTo("Lions Club Test API"))
.body("email", equalTo("testapi@lionsclub.org"))
.body("actif", equalTo(true));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testCreerOrganisation_EmailInvalide() {
OrganisationDTO organisation = createTestOrganisationDTO();
organisation.setEmail("email-invalide");
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.post("/api/organisations")
.then()
.statusCode(400);
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testCreerOrganisation_NomVide() {
OrganisationDTO organisation = createTestOrganisationDTO();
organisation.setNom("");
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.post("/api/organisations")
.then()
.statusCode(400);
}
@Test
void testCreerOrganisation_NonAuthentifie() {
OrganisationDTO organisation = createTestOrganisationDTO();
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.post("/api/organisations")
.then()
.statusCode(401);
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testListerOrganisations_Success() {
given()
.when()
.get("/api/organisations")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testListerOrganisations_AvecPagination() {
given()
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/organisations")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testListerOrganisations_AvecRecherche() {
given()
.queryParam("recherche", "Lions")
.when()
.get("/api/organisations")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
void testListerOrganisations_NonAuthentifie() {
given()
.when()
.get("/api/organisations")
.then()
.statusCode(401);
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testObtenirOrganisation_NonTrouvee() {
given()
.when()
.get("/api/organisations/99999")
.then()
.statusCode(404)
.body("error", equalTo("Organisation non trouvée"));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testMettreAJourOrganisation_NonTrouvee() {
OrganisationDTO organisation = createTestOrganisationDTO();
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.put("/api/organisations/99999")
.then()
.statusCode(404)
.body("error", containsString("Organisation non trouvée"));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testSupprimerOrganisation_NonTrouvee() {
given()
.when()
.delete("/api/organisations/99999")
.then()
.statusCode(404)
.body("error", containsString("Organisation non trouvée"));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testRechercheAvancee_Success() {
given()
.queryParam("nom", "Lions")
.queryParam("ville", "Abidjan")
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/organisations/recherche")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testRechercheAvancee_SansCriteres() {
given()
.queryParam("page", 0)
.queryParam("size", 10)
.when()
.get("/api/organisations/recherche")
.then()
.statusCode(200)
.body("size()", greaterThanOrEqualTo(0));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testActiverOrganisation_NonTrouvee() {
given()
.when()
.post("/api/organisations/99999/activer")
.then()
.statusCode(404)
.body("error", containsString("Organisation non trouvée"));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testSuspendreOrganisation_NonTrouvee() {
given()
.when()
.post("/api/organisations/99999/suspendre")
.then()
.statusCode(404)
.body("error", containsString("Organisation non trouvée"));
}
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testObtenirStatistiques_Success() {
given()
.when()
.get("/api/organisations/statistiques")
.then()
.statusCode(200)
.body("totalOrganisations", notNullValue())
.body("organisationsActives", notNullValue())
.body("organisationsInactives", notNullValue())
.body("nouvellesOrganisations30Jours", notNullValue())
.body("tauxActivite", notNullValue())
.body("timestamp", notNullValue());
}
@Test
void testObtenirStatistiques_NonAuthentifie() {
given()
.when()
.get("/api/organisations/statistiques")
.then()
.statusCode(401);
}
/**
* Test de workflow complet : création, lecture, mise à jour, suppression
*/
@Test
@TestSecurity(user = "testUser", roles = {"ADMIN"})
void testWorkflowComplet() {
// 1. Créer une organisation
OrganisationDTO organisation = createTestOrganisationDTO();
organisation.setNom("Lions Club Workflow Test");
organisation.setEmail("workflow@lionsclub.org");
String location = given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.post("/api/organisations")
.then()
.statusCode(201)
.extract()
.header("Location");
// Extraire l'ID de l'organisation créée
String organisationId = location.substring(location.lastIndexOf("/") + 1);
// 2. Lire l'organisation créée
given()
.when()
.get("/api/organisations/" + organisationId)
.then()
.statusCode(200)
.body("nom", equalTo("Lions Club Workflow Test"))
.body("email", equalTo("workflow@lionsclub.org"));
// 3. Mettre à jour l'organisation
organisation.setDescription("Description mise à jour");
given()
.contentType(ContentType.JSON)
.body(organisation)
.when()
.put("/api/organisations/" + organisationId)
.then()
.statusCode(200)
.body("description", equalTo("Description mise à jour"));
// 4. Suspendre l'organisation
given()
.when()
.post("/api/organisations/" + organisationId + "/suspendre")
.then()
.statusCode(200);
// 5. Activer l'organisation
given()
.when()
.post("/api/organisations/" + organisationId + "/activer")
.then()
.statusCode(200);
// 6. Supprimer l'organisation (soft delete)
given()
.when()
.delete("/api/organisations/" + organisationId)
.then()
.statusCode(204);
}
/**
* Crée un DTO d'organisation pour les tests
*/
private OrganisationDTO createTestOrganisationDTO() {
OrganisationDTO dto = new OrganisationDTO();
dto.setId(UUID.randomUUID());
dto.setNom("Lions Club Test API");
dto.setNomCourt("LC Test API");
dto.setEmail("testapi@lionsclub.org");
dto.setDescription("Organisation de test pour l'API");
dto.setTelephone("+225 01 02 03 04 05");
dto.setAdresse("123 Rue de Test API");
dto.setVille("Abidjan");
dto.setCodePostal("00225");
dto.setRegion("Lagunes");
dto.setPays("Côte d'Ivoire");
dto.setSiteWeb("https://testapi.lionsclub.org");
dto.setObjectifs("Servir la communauté");
dto.setActivitesPrincipales("Actions sociales et humanitaires");
dto.setNombreMembres(0);
dto.setDateCreation(LocalDateTime.now());
dto.setActif(true);
dto.setVersion(0L);
return dto;
}
}