Configure Maven repository for unionflow-server-api dependency
This commit is contained in:
@@ -0,0 +1,369 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreDTO;
|
||||
import dev.lions.unionflow.server.entity.Membre;
|
||||
import dev.lions.unionflow.server.entity.Organisation;
|
||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||
import dev.lions.unionflow.server.repository.OrganisationRepository;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour MembreImportExportService
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-19
|
||||
*/
|
||||
@QuarkusTest
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class MembreImportExportServiceTest {
|
||||
|
||||
@Inject MembreImportExportService importExportService;
|
||||
@Inject MembreRepository membreRepository;
|
||||
@Inject OrganisationRepository organisationRepository;
|
||||
@Inject MembreService membreService;
|
||||
|
||||
private Organisation testOrganisation;
|
||||
private List<Membre> testMembres;
|
||||
|
||||
@BeforeEach
|
||||
@Transactional
|
||||
void setupTestData() {
|
||||
// Créer une organisation de test
|
||||
testOrganisation =
|
||||
Organisation.builder()
|
||||
.nom("Organisation Test Import/Export Service")
|
||||
.typeOrganisation("ASSOCIATION")
|
||||
.statut("ACTIF")
|
||||
.email("org-service-" + System.currentTimeMillis() + "@test.com")
|
||||
.build();
|
||||
testOrganisation.setDateCreation(LocalDateTime.now());
|
||||
testOrganisation.setActif(true);
|
||||
organisationRepository.persist(testOrganisation);
|
||||
|
||||
// Créer quelques membres de test
|
||||
testMembres = new ArrayList<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
Membre membre =
|
||||
Membre.builder()
|
||||
.numeroMembre("UF-SERVICE-TEST-" + i)
|
||||
.nom("NomService" + i)
|
||||
.prenom("PrenomService" + i)
|
||||
.email("service" + i + "-" + System.currentTimeMillis() + "@test.com")
|
||||
.telephone("+2217012345" + (10 + i))
|
||||
.dateNaissance(LocalDate.of(1985 + i, 1, 1))
|
||||
.dateAdhesion(LocalDate.of(2022, 1, 1))
|
||||
.organisation(testOrganisation)
|
||||
.build();
|
||||
membre.setDateCreation(LocalDateTime.now());
|
||||
membre.setActif(true);
|
||||
membreRepository.persist(membre);
|
||||
testMembres.add(membre);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@Transactional
|
||||
void cleanupTestData() {
|
||||
if (testMembres != null) {
|
||||
testMembres.forEach(
|
||||
membre -> {
|
||||
if (membre.getId() != null) {
|
||||
Membre m = membreRepository.findById(membre.getId());
|
||||
if (m != null) {
|
||||
membreRepository.delete(m);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (testOrganisation != null && testOrganisation.getId() != null) {
|
||||
Organisation org = organisationRepository.findById(testOrganisation.getId());
|
||||
if (org != null) {
|
||||
organisationRepository.delete(org);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@DisplayName("Doit générer un modèle d'import Excel valide")
|
||||
void testGenererModeleImport() throws Exception {
|
||||
// When
|
||||
byte[] modele = importExportService.genererModeleImport();
|
||||
|
||||
// Then
|
||||
assertThat(modele).isNotNull();
|
||||
assertThat(modele.length).isGreaterThan(0);
|
||||
|
||||
// Vérifier que c'est un fichier Excel valide
|
||||
try (Workbook workbook = new XSSFWorkbook(new ByteArrayInputStream(modele))) {
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
assertThat(sheet).isNotNull();
|
||||
Row headerRow = sheet.getRow(0);
|
||||
assertThat(headerRow).isNotNull();
|
||||
// Vérifier la présence de colonnes essentielles
|
||||
boolean hasNom = false, hasPrenom = false, hasEmail = false;
|
||||
for (Cell cell : headerRow) {
|
||||
String value = cell.getStringCellValue().toLowerCase();
|
||||
if (value.contains("nom")) hasNom = true;
|
||||
if (value.contains("prenom")) hasPrenom = true;
|
||||
if (value.contains("email")) hasEmail = true;
|
||||
}
|
||||
assertThat(hasNom).isTrue();
|
||||
assertThat(hasPrenom).isTrue();
|
||||
assertThat(hasEmail).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
@DisplayName("Doit importer des membres depuis un fichier Excel valide")
|
||||
void testImporterDepuisExcel() throws Exception {
|
||||
// Given - Créer un fichier Excel de test
|
||||
byte[] excelFile = createValidExcelFile();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(excelFile);
|
||||
|
||||
// When
|
||||
MembreImportExportService.ResultatImport resultat =
|
||||
importExportService.importerMembres(
|
||||
inputStream,
|
||||
"test_import.xlsx",
|
||||
testOrganisation.getId(),
|
||||
"ACTIF",
|
||||
false,
|
||||
false);
|
||||
|
||||
// Then
|
||||
assertThat(resultat).isNotNull();
|
||||
assertThat(resultat.lignesTraitees).isGreaterThan(0);
|
||||
assertThat(resultat.membresImportes).isNotEmpty();
|
||||
assertThat(resultat.erreurs).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
@DisplayName("Doit gérer les erreurs lors de l'import Excel")
|
||||
void testImporterExcelAvecErreurs() throws Exception {
|
||||
// Given - Créer un fichier Excel avec des données invalides
|
||||
byte[] excelFile = createInvalidExcelFile();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(excelFile);
|
||||
|
||||
// When
|
||||
MembreImportExportService.ResultatImport resultat =
|
||||
importExportService.importerMembres(
|
||||
inputStream,
|
||||
"test_invalid.xlsx",
|
||||
testOrganisation.getId(),
|
||||
"ACTIF",
|
||||
false,
|
||||
true); // Ignorer les erreurs
|
||||
|
||||
// Then
|
||||
assertThat(resultat).isNotNull();
|
||||
assertThat(resultat.erreurs).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
@DisplayName("Doit exporter des membres vers Excel")
|
||||
void testExporterVersExcel() throws Exception {
|
||||
// Given - Convertir les membres de test en DTOs
|
||||
List<MembreDTO> membresDTO = new ArrayList<>();
|
||||
testMembres.forEach(m -> membresDTO.add(membreService.convertToDTO(m)));
|
||||
|
||||
// When
|
||||
byte[] excelData =
|
||||
importExportService.exporterVersExcel(
|
||||
membresDTO,
|
||||
List.of("nom", "prenom", "email", "telephone"),
|
||||
true, // inclureHeaders
|
||||
false, // formaterDates
|
||||
false, // inclureStatistiques
|
||||
null); // motDePasse
|
||||
|
||||
// Then
|
||||
assertThat(excelData).isNotNull();
|
||||
assertThat(excelData.length).isGreaterThan(0);
|
||||
|
||||
// Vérifier que c'est un fichier Excel valide
|
||||
try (Workbook workbook = new XSSFWorkbook(new ByteArrayInputStream(excelData))) {
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
assertThat(sheet).isNotNull();
|
||||
assertThat(sheet.getLastRowNum()).isGreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
@DisplayName("Doit exporter des membres vers Excel avec statistiques")
|
||||
void testExporterVersExcelAvecStatistiques() throws Exception {
|
||||
// Given
|
||||
List<MembreDTO> membresDTO = new ArrayList<>();
|
||||
testMembres.forEach(m -> membresDTO.add(membreService.convertToDTO(m)));
|
||||
|
||||
// When
|
||||
byte[] excelData =
|
||||
importExportService.exporterVersExcel(
|
||||
membresDTO,
|
||||
List.of("nom", "prenom", "email"),
|
||||
true, // inclureHeaders
|
||||
false, // formaterDates
|
||||
true, // inclureStatistiques
|
||||
null); // motDePasse
|
||||
|
||||
// Then
|
||||
assertThat(excelData).isNotNull();
|
||||
|
||||
// Vérifier qu'il y a plusieurs feuilles (données + statistiques)
|
||||
try (Workbook workbook = new XSSFWorkbook(new ByteArrayInputStream(excelData))) {
|
||||
assertThat(workbook.getNumberOfSheets()).isGreaterThan(1);
|
||||
Sheet statsSheet = workbook.getSheet("Statistiques");
|
||||
assertThat(statsSheet).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
@DisplayName("Doit exporter des membres vers Excel avec chiffrement")
|
||||
void testExporterVersExcelAvecChiffrement() throws Exception {
|
||||
// Given
|
||||
List<MembreDTO> membresDTO = new ArrayList<>();
|
||||
testMembres.forEach(m -> membresDTO.add(membreService.convertToDTO(m)));
|
||||
|
||||
// When
|
||||
byte[] excelData =
|
||||
importExportService.exporterVersExcel(
|
||||
membresDTO,
|
||||
List.of("nom", "prenom", "email"),
|
||||
true, // inclureHeaders
|
||||
false, // formaterDates
|
||||
false, // inclureStatistiques
|
||||
"testPassword123"); // motDePasse
|
||||
|
||||
// Then
|
||||
assertThat(excelData).isNotNull();
|
||||
// Note: La vérification du chiffrement nécessiterait d'essayer d'ouvrir le fichier avec le mot de passe
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
@DisplayName("Doit exporter des membres vers CSV")
|
||||
void testExporterVersCSV() throws Exception {
|
||||
// Given
|
||||
List<MembreDTO> membresDTO = new ArrayList<>();
|
||||
testMembres.forEach(m -> membresDTO.add(membreService.convertToDTO(m)));
|
||||
|
||||
// When - Utiliser les groupes de colonnes attendus par la méthode
|
||||
byte[] csvData =
|
||||
importExportService.exporterVersCSV(
|
||||
membresDTO,
|
||||
List.of("PERSO", "CONTACT"), // Groupes de colonnes
|
||||
true, // inclureHeaders
|
||||
false); // formaterDates
|
||||
|
||||
// Then
|
||||
assertThat(csvData).isNotNull();
|
||||
assertThat(csvData.length).isGreaterThan(0);
|
||||
|
||||
// Vérifier le contenu CSV - les en-têtes sont en français avec majuscules
|
||||
String csvContent = new String(csvData, java.nio.charset.StandardCharsets.UTF_8);
|
||||
assertThat(csvContent).contains("Nom");
|
||||
assertThat(csvContent).contains("Prénom");
|
||||
assertThat(csvContent).contains("Email");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
@DisplayName("Doit rejeter un format de fichier non supporté")
|
||||
void testFormatNonSupporte() {
|
||||
// Given
|
||||
byte[] invalidFile = "Ceci n'est pas un fichier Excel".getBytes();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(invalidFile);
|
||||
|
||||
// When & Then
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
importExportService.importerMembres(
|
||||
inputStream,
|
||||
"test.txt",
|
||||
testOrganisation.getId(),
|
||||
"ACTIF",
|
||||
false,
|
||||
false))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("Format de fichier non supporté");
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un fichier Excel valide pour les tests d'import
|
||||
*/
|
||||
private byte[] createValidExcelFile() throws Exception {
|
||||
try (Workbook workbook = new XSSFWorkbook();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
|
||||
Sheet sheet = workbook.createSheet("Membres");
|
||||
|
||||
// En-têtes
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {
|
||||
"nom", "prenom", "email", "telephone", "dateNaissance", "dateAdhesion"
|
||||
};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
}
|
||||
|
||||
// Données valides
|
||||
Row dataRow = sheet.createRow(1);
|
||||
dataRow.createCell(0).setCellValue("TestNom");
|
||||
dataRow.createCell(1).setCellValue("TestPrenom");
|
||||
dataRow.createCell(2).setCellValue("test-valid-" + System.currentTimeMillis() + "@test.com");
|
||||
dataRow.createCell(3).setCellValue("+221701234999");
|
||||
dataRow.createCell(4).setCellValue("1990-01-01");
|
||||
dataRow.createCell(5).setCellValue("2023-01-01");
|
||||
|
||||
workbook.write(out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un fichier Excel avec des données invalides pour tester la gestion d'erreurs
|
||||
*/
|
||||
private byte[] createInvalidExcelFile() throws Exception {
|
||||
try (Workbook workbook = new XSSFWorkbook();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
|
||||
Sheet sheet = workbook.createSheet("Membres");
|
||||
|
||||
// En-têtes
|
||||
Row headerRow = sheet.createRow(0);
|
||||
headerRow.createCell(0).setCellValue("nom");
|
||||
headerRow.createCell(1).setCellValue("prenom");
|
||||
headerRow.createCell(2).setCellValue("email");
|
||||
|
||||
// Données invalides (email manquant)
|
||||
Row dataRow = sheet.createRow(1);
|
||||
dataRow.createCell(0).setCellValue("TestNom");
|
||||
dataRow.createCell(1).setCellValue("TestPrenom");
|
||||
// Email manquant - devrait générer une erreur
|
||||
|
||||
workbook.write(out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreSearchCriteria;
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreSearchResultDTO;
|
||||
import dev.lions.unionflow.server.entity.Membre;
|
||||
import dev.lions.unionflow.server.entity.Organisation;
|
||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||
import dev.lions.unionflow.server.repository.OrganisationRepository;
|
||||
import io.quarkus.panache.common.Page;
|
||||
import io.quarkus.panache.common.Sort;
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
/**
|
||||
* Tests pour la recherche avancée de membres
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-19
|
||||
*/
|
||||
@QuarkusTest
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class MembreServiceAdvancedSearchTest {
|
||||
|
||||
@Inject MembreService membreService;
|
||||
@Inject MembreRepository membreRepository;
|
||||
@Inject OrganisationRepository organisationRepository;
|
||||
|
||||
private Organisation testOrganisation;
|
||||
private List<Membre> testMembres;
|
||||
|
||||
@BeforeEach
|
||||
@Transactional
|
||||
void setupTestData() {
|
||||
// Créer et persister une organisation de test
|
||||
testOrganisation =
|
||||
Organisation.builder()
|
||||
.nom("Organisation Test")
|
||||
.typeOrganisation("ASSOCIATION")
|
||||
.statut("ACTIF")
|
||||
.email("test@organisation.com")
|
||||
.build();
|
||||
testOrganisation.setDateCreation(LocalDateTime.now());
|
||||
testOrganisation.setActif(true);
|
||||
organisationRepository.persist(testOrganisation);
|
||||
|
||||
// Créer des membres de test avec différents profils
|
||||
testMembres =
|
||||
List.of(
|
||||
// Membre actif jeune
|
||||
createMembre("UF-2025-TEST001", "Dupont", "Marie", "marie.dupont@test.com",
|
||||
"+221701234567", LocalDate.of(1995, 5, 15), LocalDate.of(2023, 1, 15),
|
||||
"MEMBRE,SECRETAIRE", true),
|
||||
|
||||
// Membre actif âgé
|
||||
createMembre("UF-2025-TEST002", "Martin", "Jean", "jean.martin@test.com",
|
||||
"+221701234568", LocalDate.of(1970, 8, 20), LocalDate.of(2020, 3, 10),
|
||||
"MEMBRE,PRESIDENT", true),
|
||||
|
||||
// Membre inactif
|
||||
createMembre("UF-2025-TEST003", "Diallo", "Fatou", "fatou.diallo@test.com",
|
||||
"+221701234569", LocalDate.of(1985, 12, 3), LocalDate.of(2021, 6, 5),
|
||||
"MEMBRE", false),
|
||||
|
||||
// Membre avec email spécifique
|
||||
createMembre("UF-2025-TEST004", "Sow", "Amadou", "amadou.sow@unionflow.com",
|
||||
"+221701234570", LocalDate.of(1988, 3, 12), LocalDate.of(2022, 9, 20),
|
||||
"MEMBRE,TRESORIER", true));
|
||||
|
||||
// Persister tous les membres
|
||||
testMembres.forEach(membre -> membreRepository.persist(membre));
|
||||
}
|
||||
|
||||
private Membre createMembre(String numero, String nom, String prenom, String email,
|
||||
String telephone, LocalDate dateNaissance, LocalDate dateAdhesion,
|
||||
String roles, boolean actif) {
|
||||
Membre membre = Membre.builder()
|
||||
.numeroMembre(numero)
|
||||
.nom(nom)
|
||||
.prenom(prenom)
|
||||
.email(email)
|
||||
.telephone(telephone)
|
||||
.dateNaissance(dateNaissance)
|
||||
.dateAdhesion(dateAdhesion)
|
||||
.organisation(testOrganisation)
|
||||
.build();
|
||||
membre.setDateCreation(LocalDateTime.now());
|
||||
membre.setActif(actif);
|
||||
// Note: Le champ roles est maintenant List<MembreRole> et doit être géré via la relation MembreRole
|
||||
// Pour les tests, on laisse la liste vide par défaut
|
||||
return membre;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@Transactional
|
||||
void cleanupTestData() {
|
||||
// Nettoyer les données de test
|
||||
if (testMembres != null) {
|
||||
testMembres.forEach(membre -> {
|
||||
if (membre.getId() != null) {
|
||||
// Recharger l'entité depuis la base pour éviter l'erreur "detached entity"
|
||||
membreRepository.findByIdOptional(membre.getId()).ifPresent(m -> {
|
||||
// Utiliser deleteById pour éviter les problèmes avec les entités détachées
|
||||
membreRepository.deleteById(m.getId());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (testOrganisation != null && testOrganisation.getId() != null) {
|
||||
// Recharger l'entité depuis la base pour éviter l'erreur "detached entity"
|
||||
organisationRepository.findByIdOptional(testOrganisation.getId()).ifPresent(o -> {
|
||||
// Utiliser deleteById pour éviter les problèmes avec les entités détachées
|
||||
organisationRepository.deleteById(o.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@DisplayName("Doit effectuer une recherche par terme général")
|
||||
void testSearchByGeneralQuery() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria = MembreSearchCriteria.builder().query("marie").build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isEqualTo(1);
|
||||
assertThat(result.getMembres()).hasSize(1);
|
||||
assertThat(result.getMembres().get(0).getPrenom()).isEqualToIgnoringCase("Marie");
|
||||
assertThat(result.isFirst()).isTrue();
|
||||
assertThat(result.isLast()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
@DisplayName("Doit filtrer par statut actif")
|
||||
void testSearchByActiveStatus() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria = MembreSearchCriteria.builder().statut("ACTIF").build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isEqualTo(3); // 3 membres actifs
|
||||
assertThat(result.getMembres()).hasSize(3);
|
||||
assertThat(result.getMembres()).allMatch(membre -> "ACTIF".equals(membre.getStatut()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
@DisplayName("Doit filtrer par tranche d'âge")
|
||||
void testSearchByAgeRange() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria = MembreSearchCriteria.builder().ageMin(25).ageMax(35).build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isGreaterThan(0);
|
||||
|
||||
// Vérifier que tous les membres sont dans la tranche d'âge
|
||||
result
|
||||
.getMembres()
|
||||
.forEach(
|
||||
membre -> {
|
||||
if (membre.getDateNaissance() != null) {
|
||||
int age = LocalDate.now().getYear() - membre.getDateNaissance().getYear();
|
||||
assertThat(age).isBetween(25, 35);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
@DisplayName("Doit filtrer par période d'adhésion")
|
||||
void testSearchByAdhesionPeriod() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder()
|
||||
.dateAdhesionMin(LocalDate.of(2022, 1, 1))
|
||||
.dateAdhesionMax(LocalDate.of(2023, 12, 31))
|
||||
.build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("dateAdhesion"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isGreaterThan(0);
|
||||
|
||||
// Vérifier que toutes les dates d'adhésion sont dans la période
|
||||
result
|
||||
.getMembres()
|
||||
.forEach(
|
||||
membre -> {
|
||||
if (membre.getDateAdhesion() != null) {
|
||||
assertThat(membre.getDateAdhesion())
|
||||
.isAfterOrEqualTo(LocalDate.of(2022, 1, 1))
|
||||
.isBeforeOrEqualTo(LocalDate.of(2023, 12, 31));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
@DisplayName("Doit rechercher par email avec domaine spécifique")
|
||||
void testSearchByEmailDomain() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria = MembreSearchCriteria.builder().email("@unionflow.com").build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isEqualTo(1);
|
||||
assertThat(result.getMembres()).hasSize(1);
|
||||
assertThat(result.getMembres().get(0).getEmail()).contains("@unionflow.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
@DisplayName("Doit filtrer par rôles")
|
||||
void testSearchByRoles() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder().roles(List.of("PRESIDENT", "SECRETAIRE")).build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isGreaterThan(0);
|
||||
|
||||
// Vérifier que tous les membres ont au moins un des rôles recherchés
|
||||
result
|
||||
.getMembres()
|
||||
.forEach(
|
||||
membre -> {
|
||||
assertThat(membre.getRole())
|
||||
.satisfiesAnyOf(
|
||||
role -> assertThat(role).contains("PRESIDENT"),
|
||||
role -> assertThat(role).contains("SECRETAIRE"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
@DisplayName("Doit gérer la pagination correctement")
|
||||
void testPagination() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder()
|
||||
.includeInactifs(true) // Inclure tous les membres
|
||||
.build();
|
||||
|
||||
// When - Première page
|
||||
MembreSearchResultDTO firstPage =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 2), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(firstPage).isNotNull();
|
||||
assertThat(firstPage.getCurrentPage()).isEqualTo(0);
|
||||
assertThat(firstPage.getPageSize()).isEqualTo(2);
|
||||
assertThat(firstPage.getMembres()).hasSizeLessThanOrEqualTo(2);
|
||||
assertThat(firstPage.isFirst()).isTrue();
|
||||
|
||||
if (firstPage.getTotalElements() > 2) {
|
||||
assertThat(firstPage.isLast()).isFalse();
|
||||
assertThat(firstPage.isHasNext()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(8)
|
||||
@DisplayName("Doit calculer les statistiques correctement")
|
||||
void testStatisticsCalculation() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder()
|
||||
.includeInactifs(true) // Inclure tous les membres
|
||||
.build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getStatistics()).isNotNull();
|
||||
|
||||
MembreSearchResultDTO.SearchStatistics stats = result.getStatistics();
|
||||
assertThat(stats.getMembresActifs()).isEqualTo(3);
|
||||
assertThat(stats.getMembresInactifs()).isEqualTo(1);
|
||||
assertThat(stats.getAgeMoyen()).isGreaterThan(0);
|
||||
assertThat(stats.getAgeMin()).isGreaterThan(0);
|
||||
assertThat(stats.getAgeMax()).isGreaterThan(stats.getAgeMin());
|
||||
assertThat(stats.getAncienneteMoyenne()).isGreaterThanOrEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(9)
|
||||
@DisplayName("Doit retourner un résultat vide pour critères impossibles")
|
||||
void testEmptyResultForImpossibleCriteria() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder().query("membre_inexistant_xyz").build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getTotalElements()).isEqualTo(0);
|
||||
assertThat(result.getMembres()).isEmpty();
|
||||
assertThat(result.isEmpty()).isTrue();
|
||||
assertThat(result.getTotalPages()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(10)
|
||||
@DisplayName("Doit valider la cohérence des critères")
|
||||
void testCriteriaValidation() {
|
||||
// Given - Critères incohérents
|
||||
MembreSearchCriteria invalidCriteria =
|
||||
MembreSearchCriteria.builder()
|
||||
.ageMin(50)
|
||||
.ageMax(30) // Âge max < âge min
|
||||
.build();
|
||||
|
||||
// When & Then
|
||||
assertThat(invalidCriteria.isValid()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(11)
|
||||
@DisplayName("Doit avoir des performances acceptables (< 500ms)")
|
||||
void testSearchPerformance() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria = MembreSearchCriteria.builder().includeInactifs(true).build();
|
||||
|
||||
// When & Then - Mesurer le temps d'exécution
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 20), Sort.by("nom"));
|
||||
|
||||
long executionTime = System.currentTimeMillis() - startTime;
|
||||
|
||||
// Vérifications
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(executionTime).isLessThan(500L); // Moins de 500ms
|
||||
|
||||
// Log pour monitoring
|
||||
System.out.printf(
|
||||
"Recherche avancée exécutée en %d ms pour %d résultats%n",
|
||||
executionTime, result.getTotalElements());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(12)
|
||||
@DisplayName("Doit gérer les critères avec caractères spéciaux")
|
||||
void testSearchWithSpecialCharacters() {
|
||||
// Given
|
||||
MembreSearchCriteria criteria =
|
||||
MembreSearchCriteria.builder().query("marie-josé").nom("o'connor").build();
|
||||
|
||||
// When
|
||||
MembreSearchResultDTO result =
|
||||
membreService.searchMembresAdvanced(criteria, Page.of(0, 10), Sort.by("nom"));
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
// La recherche ne doit pas échouer même avec des caractères spéciaux
|
||||
assertThat(result.getTotalElements()).isGreaterThanOrEqualTo(0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user